git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="foo"' -- commita..commitb
Which ref do you want to rewrite?
の結果
filter-branch
では、 範囲表記を使用する 2つの任意の参照間の範囲を使用します。
このアプローチが不可能な場合、一連の連続したコミット(ブランチの履歴内のどこか)に対してフィルターを実行する最も簡単な方法は何ですか。
私が見つけた最もきれいな解決策は次のことをすることでした:
refb
に一時的なブランチを作成します。refa..temp
にブランチフィルターを適用します。ie。
git branch temp refb
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"' refa..temp
git rebase temp
git branch --delete temp
@kanが言うように、フィルターブランチを履歴の途中で適用することはできません。あなたはあなたの既知のコミットから歴史の終わりまで適用しなければなりません
git filter-branch --env-filter '...' SHA1..HEAD
フィルターブランチはコミットの作者やその他の情報をチェックして、変更するかしないかを選択できるので、あなたが望むことを達成する方法があります、 https://git-scm.com/book/en)を参照してください/ v2/Git-Tools-Rewriting-History 、「メールアドレスをグローバルに変更」を探します
覚えておいてください:コミットをパブリックリポジトリにプッシュした場合、filter-branchを使用しないでください
git filter-branch
does範囲表記を受け入れますが、範囲の終わりは、コミットのIDではなく、参照である必要があります。
git checkout -b tofilter commitb
git filter-branch .... commita..tofilter
コミットのみが与えられた場合、フィルタリングされたブランチで更新する参照がわかりません。
その範囲をチェックするifステートメントでフィルターコマンドを囲みます。次のコマンドを使用して、コミットが特定の範囲内にあるかどうかを確認できます。
git rev-list start..end | grep **fullsha**
現在のコミットは、フィルターの$GIT_COMMIT
に保存されます。したがって、フィルターは次のようになります。
git filter-branch --env-filter '
if git rev-list commita..commitb | grep $GIT_COMMIT; then
export GIT_AUTHOR_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="foo"
fi' -- ^commita --all
現在のブランチのみを書き換える場合は、--all
をHEAD
に置き換えます
コミットのsha1は親のコミットに依存するため、履歴の途中で単にコミットをオーバーライドすることはできません。したがって、gitは、フィルタリング後にHEAD参照をどこにポイントするかを認識していません。したがって、HEADまですべてを書き直す必要があります。
例:
A---B---C---D---E---F master
\
\--G---H branch
コミットBとCをフィルター処理したい場合は、D、E、F、G、Hの後のすべてのコミットもフィルター処理する必要があります。そのため、gitは範囲の最後でrefを使用するように指示し、終了しないようにします。ヘッドを取り外して持ち上げます。
BとCのコミットを変更して停止すると、次のようになります。
A---B---C---D---E---F master
\ \
\ \--G---H branch
\-B'--C' (HEAD or a temporary TAG?..)
したがって、master
とbranch
は変更されません。これはあなたが望んでいることだとは思いません。つまり、すべてのコミットをオーバーライドする必要があります。歴史はそれから:
A---B---C---D---E---F (loose end, will be garbage collected one day)
\ \
\ \--G---H (loose end, will be garbage collected one day)
\-B'--C'--D'--E'--F' master
\
\--G'--H' branch
私はこのようにします。
たとえば、branch-you-are-filteringというブランチのコンテンツをフィルタリングしたいとします。
そのブランチへの祖先コミットがあり、ref-for-commit-to-stop-atと呼ばれる参照があるとします。
git filter-branch --commit-filter 'YOUR_FILTER_COMMANDS' branch-you-are-filtering...ref-for-commit-to-stop-at
実行後、ref-for-commit-to-stop-atでのコミットは変更されません。ブランチするブランチ内のフィルターされた\変更されたコミットはすべて、ref-for-commit-to-stop-atに基づいています。
--commit-filterを使用するかどうかは、あなた次第です。
フィルターブランチの--setup
parmといくつかのシェルパワー:
git filter-branch --setup '
for id in `git rev-list commitA..commitB`; do
eval filterfor_$id=rewrite
done
rewrite() {
GIT_AUTHOR_NAME="Frederick. O. Oosball"
[email protected]
}
' --env-filter 'eval \$filterfor_$GIT_COMMIT'
@Acronの解決策は私には間違っているようです。私は以下の両方のハッシュを含むrefaとrefbを変更することをお勧めします:
git tag master.bak
git reset --hard refa
git filter-branch --env-filter ' export GIT_AUTHOR_EMAIL="[email protected]"' refa^..master
git cherry-pick refb..master.bak
git tag -d master.bak