小ネタ
git commit --fixup
とgit 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
pick
やfixup
以外にも種類があり、reword
を指定するとコミットメッセージを書き換えできる
reword xxxx hge
で保存するとrewordで指定したコミットのメッセージをEDITORで順次編集できる
rebase時に直接コメント書き換えてもOKかと思ったら編集時の書き換えは行えるが実際のコメント内容は変わらなかった
ということでコメント修正時はreword
を使う
abbreviateCommands
rebase時pick
やfixup
など頭文字一文字の省略した形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前に実行する程度ではあるが良い感じ
きれいなコミットを意識していくぞ!