🧪
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