gitコミットしぐさ
はいどうも。最近気をつけているコミットのやり方について備忘録的に書きます。1
前提として、現在はある程度成熟しているアプリケーションについての話です。新アプリの新画面ばーんってつくっていくぞみたいなときはもっと雑にコミットしてもいいんじゃないでしょうか。不具合修正であったりちょこちょこした機能追加だったりがメインな文脈です。
commit を verbose にする
いいコミットの第一歩はたぶんこれです。git CLI使っている人は git config --global commit.verbose true
でOKです。あるいは git commit -v
って打つか。2
これはどういうオプションかというと、コミットメッセージを書くときに下にdiffが出ます。
-v, --verbose Show unified diff between the HEAD commit and what would be committed at the bottom of the commit message template to help the user describe the commit by reminding what changes the commit has. Note that this diff output doesn't have its lines prefixed with #. This diff will not be a part of the commit message. See the commit.verbose configuration variable in git-config(1). If specified twice, show in addition the unified diff between what would be committed and the worktree files, i.e. the unstaged changes to tracked files.
説明にあるように、なんの変更をコミットするのかを見せてもらえるのですごくいいです。ざっと眺めることで「これってどういうタイトルつけよう?」とか「あれ、これ入れたくなかったんだけど」みたいなことが起きます。おすすめ。
リファクタリングと変更を分ける
たとえば以下のようなものを考えましょう。
SELECT * from users WHERE foo = 1 LIMIT 100;
「普通の select 文ですね。でも order by がないですね。あと from は予約語なのに小文字ですね。直しちゃいましょう。」
$ git diff diff --git a/tekitou.sql b/tekitou.sql index a9a1810..f852f3c 100644 --- a/tekitou.sql +++ b/tekitou.sql @@ -1 +1 @@ -SELECT * from users WHERE foo = 1 LIMIT 100; +SELECT * FROM users WHERE foo = 1 LIMIT 100 ORDER BY id;
はいアウトー3
from -> FROM
は動作を変更しませんが、 ORDER BY
の追加は動作を変更するので分けたほうがいいと思います。
まあこの例はさすがに極端なのですが、例えば以下のような変更をするときも2コミットに分けます。
class Foo def foo obj.some_method(another_obj.some_method) end end
ここで another_obj.some_method
を更に加工する必要が出てきたとき
まずは「リファクタリング: ローカル変数にとるようにする」のようなコミットを積んでから変更を積みます。
$ git show commit 786849cff921477a463fe7fcd59000d3ce84c0a3 (HEAD -> master) Author: hkdnet <xxx> Date: Sun Jan 28 14:12:18 2018 +0900 リファクタリング: ローカル変数にとるようにする diff --git a/tekitou.rb b/tekitou.rb index c910df5..faa7b7b 100644 --- a/tekitou.rb +++ b/tekitou.rb @@ -1,5 +1,6 @@ class Foo def foo - obj.some_method(another_obj.some_method) + tmp = another_obj.some_method + obj.some_method(tmp) end end
これの何がいいかっていうと、レビュアーが楽なんですよね。GitHubのPRにはコミットを順番に見る機能があるので4、リファクタリングって書いてあるコミットは軽く見れます。機能が変わったコミットに集中できます。
コマンドを打ったときにコミットしておく(例外あり)
たとえばこんな感じ
$ npm install foo $ git add . $ git commit -m '$ npm install foo'
npm install
で package.json
と package-lock.json
が更新されるのでそれだけでコミットします。
Gemfile
の更新は、Gemfile.lock
の更新を伴うのでだいたい一緒にしてます(例外)
$ vim Gemfile # ここではコミットしない $ bundle install $ git add . $ git commit -m 'Install awesome_gem'
Rails で generate したときもそれだけでコミットしてます。db:migrate とかも。
$ bin/rails g model User name:string $ git add . $ git commit -m '$ bin/rails g model User name:string' $ bin/rails db:migrate $ git add . $ git commit -m '$ bin/rails db:migrate'
モデルとかマイグレいじるときもコミット後に積んだほうが無難かなー。
コミットメッセージにいろいろ書く
書いておくとGitHubのPRを作るときにもコピペできて便利です。
最近だと国内向けのハイフン区切り電話番号の検証をやったのですが、こんな感じのコミットメッセージになりました。
意識してるのは、正しい仕様の根拠を示すこと。なにか機能を落としてるなら明記すること。5
$ git show commit 9a2b1b3c57308adbb2c08daaaff1459d60c2ea55 (HEAD -> master) Author: hkdnet <xxx> Date: Sun Jan 28 15:02:04 2018 +0900 xx画面での電話番号のjs検証を追加 ref: http://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/q_and_a.html#q2 電話番号は以下の仕様となる。 国内プレフィックス: 1桁(0固定) 市外局番 : 1〜4桁 市内局番 : 1〜4桁 加入者番号 : 4桁 ただし市外局番と市内局番は合計で5桁となる ハイフンは市外局番と市内局番の間、市内局番と加入者番号の間にいれる。 そのため (2-5)-(1-4)-(4) が正しいフォーマットであるといえる。 「ハイフン区切りの第1項と第2項の桁数の和が必ず6桁である」 という検証は今回は行わない ...
ハイフン区切りの第1項と第2項の桁数の和が必ず6桁である
やらなかったことが明記されてるとあとで助かります。
コミットは rebase で整形しとく
PR出す前に Fix a typo とかは rebase で何事もなかったかのように消し去ってます。
$ git commit -m 'fix a typo on xxxx' $ git rebase -i origin/master # さっきのコミットを xxxx のコミットの下の行にもってきて fixup しとく
これは好みだから別にどっちでも。僕が間違えたことやメソッドの使い方を勘違いしていたことも1つの情報だから、コミットとして残っててもいいのかもなーと思いつつ、blameで遡っていくときの邪魔になるので消しちゃうほうが最近の好みです。