notebook

都内でWEB系エンジニアやってます。

commit --fixupでコミットログをきれいにする

小ネタ

git commit --fixupgit rebase -i --autosquashを組み合わせることで簡単にコミットを混ぜられる

--fixup

git commit --fixup ${HASH}

とすることで対象のコミットハッシュと同様のコメントの前にfixup!というコメントが付く

rebase -i --autosquash

fixupでマークを付けたコミットに対してrebase時に自動で並べ替えてくれる

--fixup自体はあくまでコミットログにマークを付けるだけだがrebase -i --autosquashでエディタを開いた際にコミット順序を変えた状態で編集が始まる

なので何もせずにエディタから抜けても自動でコミットをまとめてくれる

実践

$ cat hoge.txt

$ echo 'hoge' >> hoge.txt
$ git add hoge.txt
$ git commit -m 'add hoge'
[master f0c1842] add hoge
 1 file changed, 1 insertion(+)

$ touch fuga.txt
$ git add fuga.txt
$ git commit -m 'fuga'
[master 585de87] fuga
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 fuga.txt

$ echo 'hoge' >> hoge.txt
$ git add hoge.txt : hoge.txtの修正なので以前のコミットに混ぜたい!
$ git commit --fixup f0c1842 : 'add hoge' のコミットハッシュを指定
[master c83fd8c] fixup! add hoge
 1 file changed, 1 insertion(+)
  • ここまでのログ
$ git log --oneline
c83fd8c fixup! add hoge
585de87 fuga
f0c1842 add hoge
13c72cf first commit
  • hoge.txtのdiff
c83fd8c fixup! add hoge

 hoge
+hoge

f0c1842 add hoge

+hoge

hogeを足しているコミットが2つ

git rebase -i --autosquash 13c72cf

first commitのハッシュを指定してそれ以降の履歴を変えます

  1 pick f0c1842 add hoge
  2 fixup c83fd8c fixup! add hoge
  3 pick 585de87 fuga
  4
  5 # Rebase 13c72cf..c83fd8c onto 13c72cf (3 commands)
  6 #
  7 # Commands:
  8 # p, pick <commit> = use commit
  9 # r, reword <commit> = use commit, but edit the commit message
 10 # e, edit <commit> = use commit, but stop for amending
 11 # s, squash <commit> = use commit, but meld into previous commit
 12 # f, fixup <commit> = like "squash", but discard this commit's log message
 13 # x, exec <command> = run command (the rest of the line) using shell
 14 # b, break = stop here (continue rebase later with 'git rebase --continue')
 15 # d, drop <commit> = remove commit
 16 # l, label <label> = label current HEAD with a name
 17 # t, reset <label> = reset HEAD to a label
 18 # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
 19 # .       create a merge commit using the original merge commit's
 20 # .       message (or the oneline, if no original merge commit was
 21 # .       specified). Use -c <commit> to reword the commit message.
 22 #
 23 # These lines can be re-ordered; they are executed from top to bottom.
 24 #
 25 # If you remove a line here THAT COMMIT WILL BE LOST.
 26 #
 27 # However, if you remove everything, the rebase will be aborted.

編集開始時点で並び替えがされている状態

このまま編集を抜ける

  • rebase後のlog
$ git log --oneline
0cc192b fuga
be5966d add hoge
13c72cf first commit

無事まとめられた

  • diff
add hoge

+hoge
+hoge

おまけ

reword

pickfixup以外にも種類があり、rewordを指定するとコミットメッセージを書き換えできる

reword xxxx hge

で保存するとrewordで指定したコミットのメッセージをEDITORで順次編集できる

rebase時に直接コメント書き換えてもOKかと思ったら編集時の書き換えは行えるが実際のコメント内容は変わらなかった

ということでコメント修正時はrewordを使う

abbreviateCommands

rebase時pickfixupなど頭文字一文字の省略した形p,fでも認識してくれる

configのrebase.abbreviateCommandsをtrueにすることで、EDITORでの編集時に最初から省略して表示してくれる

  • rebase時
p c1406ec fuga
f d9b77dd fixup! fuga
  • ~/.gitconfig
[rebase]
  autosquash = true
  abbreviateCommands = true

rebase.autosquashと一緒に設定しておくとらくできます

おわり

モブプロ中に指摘されてあまりそういうところ意識してやってかったなーということで復習がてら練習した

コミット粒度を細かくは意識していたけどまだ改善できそうな気がするのでしばらく意識してやってみようと思う

その後記事書くまでに使ったパターンは

  • linterの修正を適切な対象コミットに混ぜる
  • typoの修正を適切な対象コミットに混ぜる

といった用途で使った

コミットハッシュの指定はもともとpecoでコミットログ一覧を出してハッシュをコマンドラインに出力させる処理を書いていたのでそれを使っている

あまりpush -fは使いたくないのでpush前に実行する程度ではあるが良い感じ

きれいなコミットを意識していくぞ!