web-dev-qa-db-ja.com

すべてのGitコミットメッセージを編集して行を削除する

git svn を使用してSubversionから変換されたGitリポジトリがあります。元のSubversionリポジトリはもうありません。すべてのコミットメッセージには次のような行があります。

git-svn-id: file:///home/jordan/Development/wxSVG/wxsvg-svn/trunk@618 918b0bbe-f86e-4b6f-834e-cb0f658702cb

この行を削除するために、すべてのコミットメッセージを編集したいと思います。 Gitの履歴が書き換えられることは承知しており、問題ありません。各コミットを手動で編集するには非常に長い時間がかかります。これを自動化する方法があるかどうかを知りたいと思います。

私はWindowsシステムを使用していますが、Unixライクなシェルを使用しているため、Unix/Linuxコマンドで問題ありません。コミットメッセージを変更するには、なんらかの方法でsedコマンドを使用する必要があると思いますが、これをどのように行うかわかりません。

git rebase -i <commit-id>コマンドを実行すると、エディターが開き、すべてのpick値をrewordに変更する必要があります。次に、コミットごとにエディターを開いたときに、git-svn-idで始まる行を削除する必要があります。

これはどういうわけか可能ですか?

編集:見つけたばかりです この回答 なので、私の質問は重複していると見なされる可能性があります。私は今提案を試していますが、「ピック」を「リワード」に自動的に変更する答えをすでに見つけています。

2
AntumDeluge

見つかった答え ここ 解決策を見つけるのに役立ちました:

私の質問の最初の部分は、すべてのコミットが編集されるように、pickキーワードをrewordに自動的に変更する方法でした。答えは、git configのシーケンスエディタをコマンドsed -i s/pick/reword/に設定することでした。これは、-cスイッチを使用して単一のコマンドに対して実行できます。

git -c sequence.editor='sed -i s/pick/reword/' rebase -i <commit-id>

2番目の部分では、実際にすべてのコミットメッセージを変更することで、最初の部分について心配する必要がないことがわかりました。 -xスイッチを使用して、編集するコミットメッセージごとにgitコマンドを実行する必要があります。このため、シーケンスエディタを設定する代わりに、コアエディタを-c core.editor='<sed-command>'で設定する必要があります。

git rebase <commit-id> -x "git -c core.editor='sed -i s/git-svn-id.*//g' commit --amend"

コミッター名、電子メール、および日付を保存するための追加情報

**編集:**次のコマンドを使用して、各コミットの作成者情報からコミッター名、電子メール、および日付をコピーできます:
git rebase <commit-id> -x "GIT_COMMITTER_DATE=\"$(git log -1 --pretty=format:%ad)\" git -c user.name='$(git log -1 --pretty=format:%an)' -c user.email='$(git log -1 --pretty=format:%ae)' -c core.editor='sed -i s/git-svn-id.*//g' commit --amend"
**編集:**前の編集でエラーが発生しました。コミッターの日付が正しく設定されていませんでした。個々のコミットに正しい日付を使用するには、 `GIT_COMMITTER_DATE`コマンドの最後に`cat .git/rebase-merge/orig-head`を追加します:
git rebase <commit-id> -x "GIT_COMMITTER_DATE=\"$(git log -1 --pretty=format:%ad `cat .git/rebase-merge/orig-head`)\" git -c user.name='$(git log -1 --pretty=format:%an)' -c user.email='$(git log -1 --pretty=format:%ae)' -c core.editor='sed -i s/git-svn-id.*//g' commit --amend"
これにより、最新のコミットの日付だけを使用するのではなく、元のコミットのハッシュを使用して日付が取得されます。


編集:リベースでGIT_COMMITTER_DATE環境変数を使用して各コミットのコミッター日付を保存するのに問題がありました。ですから、遊んだ後、git cherry-pickでやりたいことができました。これはこれを達成するための最良の方法ではないかもしれませんが、私にとってはうまくいきました。

最初に、すべてのコミットハッシュのリストを逆の順序で作成しました(<start-commit>は含まれていないことに注意してください:

git log --reverse --format="%H" <start-commit>...<end-commit> > ../hashes.txt

次に、次のループコマンドを使用して、コミッター名、電子メール、日付を保持しながら各コミットを個別に追加しました(コミットメッセージを変更する必要がない場合は、-c core.editor='<editor-command>'を省略し、--no-editオプションをcommitコマンドに追加します)。

for COMMIT in $(cat ../hashes.txt); do \
  git cherry-pick $COMMIT && \
  GIT_COMMITTER_DATE="$(git log -1 --format=%cd $COMMIT)" git -c user.name="$(git log -1 --format=%cn $COMMIT)" -c user.email="$(git log -1 --format=%ce $COMMIT)" -c core.editor='sed -i s/git-svn-id.*//g' commit --amend; \
  if [ "$?" -ne "0" ]; then break; fi; done

if [ "$?" -ne "0" ]; then break; fi;コードは、チェリーピックが失敗した場合にループを強制的に終了させます。これが発生した場合は、続行する前にhashes.txtファイルからすべてのハッシュを削除する必要があります。チェリーピックの進行中に停止した場合は、競合を解決してからgit cherry-pick continueを使用する必要があります。次に、続行する前に、コミットを手動で修正して、コミッター名、電子メール、および日付を設定する必要があります。

2
AntumDeluge