理系学生日記

おまえはいつまで学生気分なのか

コミット履歴を綺麗にするときの`git commit --fixup`と`git rebase --autosquash`

Pull Request(PR)やMerge Request(MR)を作る中で、コミット履歴はできるだけ綺麗にしておきたいものです。

ぼくはあまりコミット履歴の綺麗さを気にしない方でした。 しかし大きめのPRやMRをレビューする側に回ると、「変更のまとまり」が追えないと「なぜこの変更をしたのか」が非常に追いにくくなります。 だからこそ最近は、コミット履歴をかなり意識するようになりました。

その時に活躍しているのが、タイトルの通りgit commit --fixupgit rebase --autosquashです。

git commit --fixup

git commit --fixupのhelpを見ると、引数としてcommit hash等を取り、 git rebase --autosqushと組み合わせて使うものであることが読み取れます。

$ git help commit | grep -A3 '^\s*--fixup'
       --fixup=<commit>
           Construct a commit message for use with rebase --autosquash. The
           commit message will be the subject line from the specified commit
           with a prefix of "fixup! ". See git-rebase(1) for details.

実際に使ってみましょう。 例えば、本エントリを書いている際のコミット履歴がこのようになっていたとします。

$ git log --oneline -2
07d0cf3 (HEAD -> master) add: コミット履歴を綺麗にするときの`git commit --fixup`と`git rebase --autosquash`
1312f4d (origin/master, origin/HEAD) add: 付加年金と国民年金基金

ここでgit commit --fixupを実行すると以下のようになり、コミットメッセージが「指定したコミットのメッセージにfixup!がついたもの」になりました。

$ git add -u
$ git commit --fixup=07d0cf3
[master a1a197c] fixup! add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`
 1 file changed, 10 insertions(+)

何度か同じことを実行し、別のコミットも重ねてみました。 ここでコミットログを見てみましょう。以下のようにfixup!のコミットログが散在している状態になりました。

$ git log --oneline -6
359776e (HEAD -> master) fixup! add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`
f021fcb add: rebaseの説明
58c7455 fixup! add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`
64e68b0 fixup! add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`
a1a197c fixup! add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`
07d0cf3 add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`

git rebase --autosquash

ここでgit rebase --autosquashを実行してみます。

$ git rebase --autosquash 07d0cf3~
Created autostash: cf1f2ce
Current branch master is up to date.
Applied autostash.

ぼくはVS CodeにGitLens — Git superchargedを入れているので、以下のようなタブが起動しました。 散在していたfixup!が1つに並び、容易にコミットをまとめることができる状態になっています。

この状態でrebaseを完了させると、以下のようにまとまったコミットログを作ることができました。

$ git log --oneline -4
b8b04a3 (HEAD -> master) add: rebaseの説明
5323274 add: コミット履歴を綺麗にするときの`git commit --fixup``git rebase --autosquash`
1312f4d (origin/master, origin/HEAD) add: 付加年金と国民年金基金
2f17841 add: 「モノリスからマイクロサービスへ」の1章、2章を読んだ

このようにgit commit --fixupgit rebase --autosquashを組み合わせることで、コミットを整理した綺麗なコミットログを作ることができます。

$ git help rebase | grep -A11 '^\s*--autosquash'
       --autosquash, --no-autosquash
           When the commit log message begins with "squash! ..." (or "fixup!
           ..."), and there is already a commit in the todo list that matches
           the same ..., automatically modify the todo list of rebase -i so
           that the commit marked for squashing comes right after the commit
           to be modified, and change the action of the moved commit from pick
           to squash (or fixup). A commit matches the ...  if the commit
           subject matches, or if the ...  refers to the commit's hash. As a
           fall-back, partial matches of the commit subject work, too. The
           recommended way to create fixup/squash commits is by using the
           --fixup/--squash options of git-commit(1).

そのほかおすすめ

.gitconfigに以下を設定すると捗るのではないかと。

  • rebase.autoSquash
  • rebase.abbreviateCommands