[Git]プッシュ済みのコミットをamendしてしまった時の対処

2020.04.08

こんにちは、CX事業本部の若槻です。

Gitでの開発作業で、うかつにもプッシュ済みのコミットをローカル側でamendにより変更しまった際の対処方法について確認をしました。

プッシュ済みのコミットをamendしてしまった

git commitコマンドの--amendオプションを使えばすでに作成されたコミットの内容を変更することができます。コミットに入れ忘れた変更を駆け込みで追加したい場合などに便利なオプションです。

さて、いつもの開発作業でgit commit --amendコマンドを使ってコミットの変更を行いました。

$ git commit --amend
[feature 534506c] fix
 Date: Wed Apr 8 10:54:14 2020 +0000
 1 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 hoge.txt

ところが不注意にも、この時amendしたのはGitHub上のリモートブランチにプッシュ済みのコミットでした。気付いた時には時すで遅しで、ブランチのHEADのコミットがリモートとローカルの間で競合状態となってしまいました…。

よって、この状態ではgit pushをしても以下のようにrejectされてしまいます。(git pullをするとコンフリクトも起こします。)

$ git push origin feature
To https://github.com/account/test.git
 ! [rejected]        feature -> feature (non-fast-forward)
error: failed to push some refs to 'https://github.com/account/test.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: 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.

競合したコミットをローカル側でamend前に戻す

このような場合にはローカル側のHEADのコミットをリモート側に合わせることにより、競合状態となったコミットをローカル側でamend前の状態に戻すことで対処が可能です。

ローカルブランチのHEADのコミットをリモートブランチのHEADで上書きしたい時はgit reset origin/<ブランチ>コマンドを使います。

競合が発生したブランチでコマンドを実行します。

$ git reset origin/feature
Unstaged changes after reset:
M       hoge.txt

すると先ほどamendでコミットに入れた変更が作業ツリーに移り、コミットをamend前の状態に戻すことができました。

$ git status
On branch feature
Your branch is up-to-date with 'origin/feature'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   hoge.txt

no changes added to commit (use "git add" and/or "git commit -a")

あとはこの変更を既存コミットでのamendではなく、ちゃんと新しいコミットに入れてあげれば問題ないはずです。

おわりに

プッシュ済みのコミットをローカル側でamendにより変更しまった際に、ローカル側でコミットをamend前の状態に戻すことにより対処する方法をご紹介しました。

今回の方法は「ローカル側をリモート側に合わせる」対処でした。逆にamendしたコミットを強制プッシュして「リモート側をローカル側に合わせる」ことも出来なくはないですが、リモートリポジトリを壊すリスクがある(特にチームで開発を行っている場合など)ので、極力ローカル側の対処で解決するようにしましょう。

以上