19.1K Views
August 04, 22
スライド概要
ぼくのかんがえたさいきょうの開発環境 天下一武道会で発表したスライドです。
`wip`エイリアス
```
alias wip='git commit --fixup $(git log -1 --pretty=format:"%H" --grep="^fixup\!" --invert-grep)'
```
このスライドのコード
https://github.com/korosuke613/zenn-articles/tree/9498a8a6f03791b8619dfd4f759f11f3e4311ab2/slides/git-commit-fixup
サイボウズ株式会社 開発本部 生産性向上チームで働いています。
がんばれ`fixup`と`autosquash` おまえがナンバー1だ!! (WIP コミットにおいて) 2022/08/04 (木) ぼくのかんがえたさいきょうの開発環境 天下一武道会 平木場 風太 <Futa Hirakoba> 🥊
平木場 風太 - Futa Hirakoba 🌋 出身 - 鹿児島 🏢 勤め先 - サイボウズ株式会社 / 開発本部 / 生産性向上チーム 🧑💻 役割 - Engineering Productivity 🍣 好きな食べ物 - チキン南蛮、辛麺 💪 AWS や CI、Terraform を触ることが多い [1] @korosuke613 @shitimi_613 1. 写真は桝元の辛麺(トマト 5 辛中華麺チーズトッピング)。毎日食べたい。 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 2 / 22 ]
今日話すこと `git commit --fixup` と `git rebase --autosquash` をうまく使って WIP コミットの作成とマージを高速にやっていくよ ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 3 / 22 ]
WIP コミットとは? トピックブランチで作業中、作業途中の状態を保存目的でコミットを積むこと[1][2] 個人作業だけでなくモブプログラミングのドライバー交代時に登場することも `git commit -m "wip"` というふうにしがち fix :. .. fe at :. .. main 3 w ip 2 w ip 1 w ip fe at :h og e develop 1. 平木場による造語。 2. `git commit --amend --no-edit` でもいいけどプッシュ時に force push しないといけないため、めんどい&あんまりやりたくない。 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 4 / 22 ]
WIP コミットはマージ前にまとめる 開発 & WIP コミットを繰り返す 完成したら main ブランチへマージ前に WIP コミットはまとめる ヒストリーに WIP コミットを残したくないよね まとめるのには `git rebase --interactive` などのコマンドを使いがち fix :. .. fe at :. .. main fe at :h og e develop ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 5 / 22 ]
WIP コミットを使った開発の流れ 意味のあるメッセージのコミットを作成 コーディング WIP WIP コミット コミットを意味のあるメッセージのコミットにマージ # 準備 git commit --allow-empty -m "feat: hoge" [topic b13be29] feat: hoge ❯ git push origin HEAD ❯ コミットを積んでいく # WIP ❯ vim hoge ❯ git add hoge ❯ git commit -m "wip" [topic 188ff3b] wip 1 file changed, 123 insertions(+) create mode 100644 hoge vim hoge git add hoge git commit -m "wip" [topic 0a4efa9] fixup! hoge 1 file changed, 10 insertion(+), 2 deletions(-) ❯ ❯ ❯ まとめたコミットをプッシュ # ❯ ❯ コミットをまとめてプッシュ git rebase --interactive main git push --force-with-lease ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 6 / 22 ]
`git rebase --interactive`
マージ先ブランチ名>` をするとインタラクティブに rebase できる
`git rebase --interactive <
デフォルトエディタ[1]が立ち上がるので、コミットごとにコマンドを指定する
pick acea229 feat: hoge
pick fa27bfa wip
pick 2795746 wip
#
#
#
#
#
#
#
#
#
#
#
#
Rebase 6be49d1..2795746 onto 6be49d1 (3 commands)
Commands:
p, pick <commit> =
r, reword <commit>
e, edit <commit> =
s, squash <commit>
f, fixup [-C | -c]
省略>
<
use commit
= use commit, but edit the commit message
use commit, but stop for amending
= use commit, but meld into previous commit
<commit> = like "squash" but keep only the previous
commit's log message, unless -C is used, in which case
keep only this commit's message; -c is same as -C but
opens the editor
1. `$EDITOR` または `$VISUAL` または git config の `core.editor` に設定されているエディタ。どれも設定されてなければ `vi` が使わ
れる。設定の優先順位は知らない。
ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 7 / 22 ]
`git rebase --interactive`
今回はコミットをまとめたいので `pick` の部分を `fixup` に変える[1][2]
`fixup` を指定したコミットは 1 つ上のコミットにマージされる。ただし、コミットメッセージは 1 つ上の
ものが使用される
エディタが Vim なら `Shift` + `v` -> fixup したいコミットの行を選択 -> `:'<,'>s/pick/fixup/g` で
複数の `pick` を `fixup` に置き換えられる
pick acea229 feat: hoge
fixup fa27bfa wip
fixup 2795746 wip
省略>
<
1. `fixup` 以外にも便利なコマンドがたくさんある。みんな `git rebase --interactive` を使いこなしてくれよな!コミットの順序を
入れ替えることだってできるぞ!
2. `fixup` の代わりに `f` でも可。
ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 8 / 22 ]
`git rebase --interactive` エディタを保存して終了すると `fixup` で指定したコミットが 1 つ若い(古い)コミットにマージされる before git log main.. --oneline 2795746 (HEAD -> topic) wip fa27bfa wip acea229 feat: foo 6be49d1 (main) feat: hoge ❯ after git log main.. --oneline dbe67da (HEAD -> topic) feat: foo 6be49d1 (main) feat: hoge ❯ 今回の例では「feat: foo (acea229)」にマージされる この後はヒストリーがきれいになったので force push して main ブランチにマージする ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 9 / 22 ]
`pick` を `fixup` に 変えていくのめんどいな 🤔 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 10 / 22 ]
というわけで本題に入ります ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 11 / 22 ]
`git rebase --autosquash` マージ対象コミットのハッシュまたはメッセージ>` となっているコミットの コミットメッセージが `fixup! < コマンドを自動で `fixup` にしてくれる[1] マージ対象コミットの真下になるように並び替えもしてくれる `--interactive` も必要[2] 1. 他にも `squash!` や `amend!`、`fixup! -C` などがある。https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt--autosquash 2. `--interactive` をつけなくてもできる方法知っている人いたら教えてください。 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 12 / 22 ]
`git rebase --autosquash` git log main.. --oneline e5c1a0f (HEAD -> topic) fixup! feat: hoge 1ec880d fixup! feat: hoge 83791fc feat: hoge ❯ `git rebase --interactive --autosquash main` pick 83791fc feat: hoge fixup 1ec880d fixup! feat: hoge fixup e5c1a0f fixup! feat: hoge 省略> < `fixup!` のコミットのコマンドが最初から `fixup` となっている ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 13 / 22 ]
毎回コミットメッセージを `fixup! 〜` ってするのめんどいな 🫠 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 14 / 22 ]
`git commit --fixup`
`git commit --fixup <
マージ対象コミットのハッシュ>` を実行すると自動で `fixup!` のコミットメッセ
ージを作成してくれる
マージ対象コミットのメッセージ>` という形式になる[1]
`fixup! <
git commit --fixup c0af36
[fixup 2e719be] fixup! feat: hoge
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 ccaca
❯
マージ対象コミットのハッシュ>` とならないのかは知らない。人間が読むのを想定してるから?rebase 時にコミットハ
1. なんで `fixup! <
ッシュが変わってしまう可能性があるから?
ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 15 / 22 ]
毎回マージ対象のコミットハッシュを打ち込むのめんどいな 🫥 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 16 / 22 ]
`git commit --fixup` はコミットハッシュを指定し ないといけないからめんどい `git commit --fixup < マージ対象コミットのハッシュ>` しないといけない WIP コミットを作るたびにマージ対象コミットのハッシュを指定するのがめんどい `HEAD` を指定するのはどうだい? `git commit --fixup HEAD` にすると HEAD のコミットを指定することになるので、常に HEAD を指 定すると `fixup!` の先のコミットへマージされることになる ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 17 / 22 ]
`git commit --fixup HEAD` してみる 変更を加えるたびに `git commit --fixup HEAD` を実行する 現実は非情だった![1] 1199b2a 637a150 2e719be c0af36a (HEAD -> topic) fixup! fixup! fixup! feat: hoge fixup! fixup! feat: hoge fixup! feat: hoge feat: hoge HEAD のコミットメッセージが入るため、永遠に `fixup!` が増えていくことになる 見づらいし、いつかメッセージサイズの限界が来る 1. `--autosquash` したらちゃんと `c0af36a` 以外のコミットのコマンドは `fixup` となる。 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 18 / 22 ]
じゃあもう自動でマージ対象コミットを取ってくるか 要は `fixup!` でないコミットハッシュを取ってくればいい `git log -1 --pretty=format:"%H" --grep="^fixup\!" --invert-grep` で取ってこれる `-1`: 一番新しい 1 コミットだけ表示 `--pretty=format:"%H"`: コミットハッシュだけ表示 `--grep="^fixup\!"`: `fixup!` で始まるコミットメッセージのコミットを抽出 `--invert-grep`: `--grep` の結果を反転させる 例)`fixup!` で始まらない `feat: hoge` のコミットハッシュのみが表示される git log main.. --oneline c801878 (HEAD -> topic) fixup! feat: hoge dbae606 fixup! feat: hoge c855557 fixup! feat: hoge 667f80d feat: hoge ❯ git log -1 --pretty=format:"%H" --grep="^fixup\!" --invert-grep 667f80dafbb9449c0d0f1aeff9831afb234af434 ❯ ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 19 / 22 ]
最終的なコマンド
`--fixup` の引数にハッシュ取得コマンドを埋め込む
git commit --fixup $(git log -1 --pretty=format:"%H" --grep="^fixup\!" --invert-grep)
wip みたいな名前で alias 化
alias wip='git commit --fixup $(git log -1 --pretty=format:"%H" --grep="^fixup\!" --invert-grep)'
例)
git log main.. --oneline
c801878 (HEAD -> topic) fixup! feat: hoge
dbae606 fixup! feat: hoge
c855557 fixup! feat: hoge
667f80d feat: hoge
❯
wip
[fixup dbae606] fixup! feat: hoge
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar
❯
ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 20 / 22 ]
まとめ `git rebase` の `--autosquash` オプションを使うと WIP コミットをまとめるのが楽になる `git commit` の `--fixup` オプションを使うと `fixup! ~` コミットメッセージをつけるのが楽になる `git commit --fixup $(git log -1 --pretty=format:"%H" --grep="^fixup\!" --invert-grep)` を使うと `--fixup` するのが楽になる さらに alias 化すると `--autosquash` のための WIP コミットの作成を 1 コマンドでできて楽 結論: 開発力が 53 万になる ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 21 / 22 ]
参考情報 Fixing commits with git commit --fixup and git rebase --autosquash | Jordan Elver[1] `--fixup` と `--autosquash` の解説記事 tummychow/git-absorb: git commit --fixup, but automatic[2] `git commit --fixup` 周りをいい感じに行うツール Slidev[3] このスライドは Slidev というスライド作成ツールで作りました[4] マークダウンとか HTML とかで作れるよ 1. https://jordanelver.co.uk/blog/2020/06/04/fixing-commits-with-git-commit-fixup-and-git-rebase-autosquash/ 2. https://github.com/tummychow/git-absorb 3. https://sli.dev 4. https://github.com/korosuke613/zenn-articles/pull/236 ぼくのかんがえたさいきょうの開発環境 天下一武道会 - [ 22 / 22 ]