🧪

git reset --hard で取り消したコミットで、特定のコミットだけ復活させる

に公開

前提条件

※Git は以下バージョンを使用しております。バージョンが古い場合、以下記載されてる挙動が動かない場合があります。

  • Git v2.47.1

背景

git reset --hard で複数コミットを取り消すケースがあったとき、稀に取り消した特定のコミットだけ復活させたい時がある。
大半のソースが git reflog 使って、git reset させるパターンだったが、それだと全コミットが復活してしまうので、備忘録も兼ねて、記載する。

結論: git cherry-pick で復活できる

例として、以下のコミットがあったとする。

$ git log --oneline
d36bdc0 (HEAD -> main) feat: second commit
417db6d feat: first commit

次に git reset --hard を実行してみる。

$ git reset --hard 417db6d
HEAD is now at 417db6d feat: first commit

git log で確認すると、コミットが取り消されてるのが確認できる。

$ git log --oneline
417db6d (HEAD -> main) feat: first commit

この状態で 取り消したコミットハッシュ d36bdc0 を指定して git cheery-pick を実行してみる。

$ git cherry-pick d36bdc0
[main 6aab761] feat: second commit
 Date: Mon Feb 3 15:28:14 2025 +0900
 1 file changed, 3 insertions(+)

git log で確認すると、コミットが復活している
(実際はコミットハッシュが変わっているので、再生成のほうが正しいかも)

6aab761 (HEAD -> main) feat: second commit
417db6d feat: first commit

なぜ、復活できるのか?

実は、コミットハッシュは git reflog でも記録されている。なので、実際は git reflog に記録されてるコミットを参照して、cherry-pick している。

da90fa0 (HEAD -> main) HEAD@{0}: cherry-pick: feat: second commit
417db6d HEAD@{1}: reset: moving to 417db6d
6aab761 HEAD@{2}: cherry-pick: feat: second commit
417db6d HEAD@{3}: reset: moving to 417db6d
d36bdc0 HEAD@{4}: commit: feat: second commit
417db6d HEAD@{5}: commit (initial): feat: first commit

おまけ: コミットさせずに、差分だけ復活させたい場合

git cherry-pick --no-commit で差分だけ復活させることができる。

$ git cherry-pick --no-commit d36bdc0
# 省略 ver
$ git cherry-pick -n d36bdc0

まとめ

  • 取り消したコミットを特定のものだけ復活させる場合は git cherry-pick {commit hash} で復活できる
  • コミットさせずに、差分だけ復活させたい時は --no-commit オプションを付与する

Discussion