Git でリモートに push 済みのコミットを amend したときの対応方法
Git でリモートに push した後のコミットを、ローカルで commit --amend
で変更してしまった場合の対応方法についてです。
凡ミスにより年に数回はこの状況に遭遇するので、やり方をまとめておきます。
対応オプション
対応方法のオプションがいくつかあります。
- a.
git push
に--force
(-f
)オプションをつけて無理やり push する - b. 対象のコミットを soft
reset
してからコミットし直す - c. リモートをマージしてコンフリクトを解消した新たなコミットを作る
これらのうち、オプション a は、リモートに変更が無いことを 100% 確信できる場合にかぎり使ってもよいような気もします。 ただ、万が一リポジトリを壊してしまった場合の手間が大変そうなので、個人的には現実的なオプションは b か c だと思います。 b と c の比較でいうと心理的な負担が少ないのは c の方なので、個人的には c を選んでいることが多いと記憶しています。
ということで、以下、 c の方法についてその流れをかんたんに説明します。
対応の流れ
全体の流れは、「リモートのブランチを改めてローカルで merge して、コンフリクトを解消した新たなコミットを作って、 push し直す」という流れになります。
以下サンプルコードです。
$ # push 済みのローカルのコミットを変更してしまった...$ git commit --amend$ # 齟齬があるため push は当然失敗する...$ git push origin masterTo ssh://[リモートリポジトリの URI]! [rejected] master -> master (non-fast-forward)error: failed to push some refs to 'ssh://[リモートリポ ジトリの URI]'hint: Updates were rejected because the tip of your current branch is behindhint: its remote counterpart. Integrate the remote changes (e.g.hint: 'git pull ...') before pushing again.hint: See the 'Note about fast-forwards' in 'git push --help' for details.$ # 以下 1-6 で対応$ # 1. まずはリモートの HEAD を fetch する$ git fetch origin master$ # 2. (オプション)リモートとローカルのブランチに差分があることを確認する$ git diff --shortstat master..origin/master1 2 files changed, 79 insertions(+), 1 deletion(-)$ # 3. リモートの( amend 前の)コードを merge する$ git merge origin/masterAuto-merging [変更のあったファイル 1]CONFLICT (content): Merge conflict in [変更のあったファイル 1]Auto-merging [変更のあったファイル 2]CONFLICT (content): Merge conflict in [変更のあったファイル 2]Automatic merge failed; fix conflicts and then commit the result.$ # 4. auto-merging がコンフリクトで失敗するので、コンフリクトをひとつずつ解消する$ open [変更のあったファイル 1]$ open [変更のあった ファイル 2]$ # 5. コンフリクトを解決したらその内容を新たにコミットする$ git add [変更のあったファイル 1] [変更のあったファイル 2]$ git commit -m '[コミットメッセージを適当に]'$ # 6. 改めて push して終了$ git push origin master
以上です。
軽微な変更を繰り返しているときについついやってしまうので、スムーズに対応できるようにしたいものです。