やること
コミットの履歴を直したい場合に使用するコマンド等の解説をします。
コミットを整理する際に使用するコマンド
git commit --amend
git commit --ammend
を使用すると、現在のステージングの内容を直前のコミットに含めることができます。
git stash
現在の変更を一時的に退避するコマンドです。
直接コミットの履歴を改変するものではありませんが、例えばgit reset
(後述)などでコミットを作業ツリーに戻した際に使用したりします。
git rebase -i
過去のコミットを対話形式で修正するためのコマンドです。
git reset
コミットを取り消す(作業ディレクトリへ戻す)ために使用します。
実践
例えば以下のようなコミット履歴があるとします。
f4a348b class B をさらに修正
770be22 class B を一部修正
064dd2a class C を作成
55af461 class B を作成
2ef7ce5 class A を作成
修正分のコミットはコミットの歴史としてはノイズになりやすいので、可能であれば以下のような状態が望ましいとします。
064dd2a class C を作成
55af461 class B を作成
2ef7ce5 class A を作成
こちらの方がコミット履歴としては自然ですし、プルリクエストなどのレビューに際してレビュアーもレビューがしやすくなるでしょう。
そこで、過去のコミットを改変(整理)してみようと思います。
#はじめに手順概要
git reset HEAD~2 -- 直近のコミット2つを取り消す
git stash -- 上記で取り消した変更を退避させる(後に取り込む)
git rebase -i HEAD~2 -- 過去のコミットを改変する状態とする
git stash pop -- 2つ目の手順で退避した変更を作業ツリーに戻す
git add . -- 上記で作業ツリーに戻した分をステージングに移動
git commit --amend -- 過去のコミットに変更分を含める
git rebase --continue -- rebaseを終了
手順詳細
git reset
まずはgit reset
コマンドを使用して、コミットした変更を作業ツリーに戻します。
git reset HEAD~2
この時点で、コミットログは以下のようになります。
064dd2a class C を作成
55af461 class B を作成
2ef7ce5 class A を作成
最新のコミットが2つなくなり、変更箇所が作業ツリーに戻っています。
git stash
git stash
を使用して作業ツリーに残っている変更を退避させます。
git rebase -i
次に、git rebase -i
を使用して過去のコミットを改変します。
今回は、classBの変更分(現在git stash
により退避中)をclassBを作成した際のコミットに含めるようにします。
git rebase HEAD~2
を実行します。
すると以下のような編集画面が現れます。今回、コミットを改変したいのはClassBの作成に関わる箇所のため、一番上の行の左端の文言をedit
に修正します。
pick 55af461 Class B を作成
pick 064dd2a Class C を作成
↓
edit 55af461 Class B を作成
pick 064dd2a Class C を作成
編集したら:wq
で編集画面を抜けます。
この状態になると、ClassBを作成した時のコミットを修正状態となります。
git stash pop ~ git commit --amend
先ほどgit stash
したClassBの変更点をgit stash pop
で再度取り込みます。
修正内容が作業ツリーに戻ってきているため、git add
でステージングに追加します。
最後にgit commit --amend
を実行すると、Class Bを作成したコミットが、元々修正としてコミットされた変更分も合わせた状態となります。
余談
私も以前そうだったのですが、Git
のコミット履歴が汚くなってしまう部分については往々にして作業の分割がうまくいっていないように思います。最初からコミット履歴が綺麗であればコミットの整理という作業も発生しないので、自分がこれからする作業についてどういった順序や粒度で進めていくかを一旦手を止めて考えてみるといいかもしれません。(予定を立ててもその通りにいかないというのは世の常ですが・・。)
終わりに
素敵なGit
ライフを。