💬
過去の特定のコミットを削除する方法
過去の特定のコミットを削除する方法として
-
git rebase -i HEAD~n
(nは自然数で最新のコミットからいくつ戻るか)で特定のコミットを選び、drop
で削除することができる。rebaseには他にもsquash
やfixup
等のオプションがあります。
追記(JST, 2024年12月20日7時)
git rebase -i --root
によって、最初のコミットまでの全てのコミット履歴がrebase出来るようになる。ここでrebaseするためのファイル内でdrop
やsquash
によって削除することができる。自分のリポジトリで行ったところ、コミット間のコンフリクトを直せば無事削除することが出来た。しかし、コミットIDが全て書き変わりVSCodeのGUIでのツリーを見たところ、rebaseで行ったからか下の方法ではツリーが分岐していたが分岐していなかった。どちらにしろコミットIDが全て書き変わり見やすくなるこちらの方が良い可能性がある。最初のコミットをここで取り除くような操作をしてしまうと、emptyコミットが代わりに作成される。これについては良くわからないので各自で調べてほしい。 - 特定のコミットの親コミットから新しいブランチを作成する。削除したいコミット以降のコミットを新しいブランチに適用する。元のブランチに切り替えて変更を取り込む。
追記(JST, 2024年12月15日23時)
こちらの方法で新しいブランチからcherry-pickしたら、コミットIDも全て書き変わってしまい元のブランチの名前で内部構造は別のブランチになっているらしいです。ブランチはコミットのポインタとして動いているはずですので、ブランチからcherry-pickしたら元のブランチのポインタが新しく作られたブランチへのポインタへ追加されるような感じかもしれないです。非推奨な気がするので、git rebase -i
でコンフリクトと戦った方がいいかもしれないです。
自分の場合
git rebase
でコンフリクトが多かったこととマージするときにマージコミットが反映されてしまった。削除したいコミットが何故か直ってなかった。上記の障害が起きてしまったので、シンプルに新しいブランチで直してから取り込むことにした。
やり方
削除したいコミットの親コミットから新しいブランチを作成
git checkout -b <new-branch-name> <parent-commit-id>
新しいブランチへの移動
git switch <new-branch-name>
元のブランチにある削除したいコミット以降のコミットを新しいブランチに適用。例:git cherry-pick 1e0cd2..main
でコミットID1e0cd2
の次のコミットからmainの指し示すコミットIDまでを適用できる。
git cherry-pick <commit-id-to-remove>..<orig-branch-name>
元のブランチに戻る
git switch <ogirinal-branch-name>
新しいブランチの情報で元のブランチの情報を強制的に書き換える。ここでマージなどを行うとコンフリクトが発生してしまう可能性があるので注意する。
git reset --hard <new-branch-name>
リモートも強制的に上書き
git push --force origin <original-branch-name>
まとめ
一人でブランチやコミットをこねくり回すには別になんともないかもしれないですが、チーム開発ではおこなわないようにしましょう。一人用のリポジトリですらコンフリクトの修正が大変でした。
Discussion