git のコミットを適切に作れていますか?
自分はコードを書く前にTODOを作成しますが、どのようにコミットを分けるかも意識しています(TODO ≒ コミット)
ただ最初から全てが見えていない時もあり、予定通りコミットを分けることができないこともあります。
後からコミットを整理しますが、ファイル単位だけでなく同じファイル内の修正でも別コミットにしたい時がありますよね。
そんな時にgit add -p
使ってコミットを整理します。
git add -p
とは
git add --help
でヘルプを確認します。
-p, --patch
Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to
修正のまとまり(hunk)をインタラクティブに選択して、インデックスに追加することができます。
ファイル単位だけでなく、自分で行を選択してインデックスに追加できるので、細かくコミットを作ることができます。
インタラクティブモード時のコマンド
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
たくさんありますがy
, n
, q
, s
, e
あたりを使えれば良いと思います。
やってみる
実際に以下のファイルを修正していきます。
def hello
puts 'Hello'
aaa
end
def good
puts 'Gooood'
end
def nice
puts 'Nice'
end
hello
good
- 修正内容
- 不要なaaaを削除
- Goodのtypo修正
- niceメソッドの呼び出し追加
diff --git a/sample.rb b/sample.rb
index e828f1c..92cd6cb 100644
--- a/sample.rb
+++ b/sample.rb
@@ -1,10 +1,9 @@
def hello
puts 'Hello'
- aaa
end
def good
- puts 'Gooood'
+ puts 'Good'
end
def nice
@@ -13,3 +12,4 @@ end
hello
good
+nice
この修正を1つのコミットではなく3つのコミットに分けるためにgit add -p
を使っていきましょう。
(1/2) Stage this hunk
と表示されているので、2つのhunkに分かれています。
aaaの削除と、Goodのtypo修正が同じhunkになっているので分けたいですね。
その時はs
で分割します。
❯ git add -p
diff --git a/sample.rb b/sample.rb
index e828f1c..92cd6cb 100644
--- a/sample.rb
+++ b/sample.rb
@@ -1,10 +1,9 @@
def hello
puts 'Hello'
- aaa
end
def good
- puts 'Gooood'
+ puts 'Good'
end
def nice
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,s,e,?]? s
(1/3) Stage this hunk
となり3分割されました。
aaaの削除だけになったのでy
でインデックスに追加、残りはn
でインデックスに追加しないようにします(q
で残りを全て追加しないでもok)
あとはコミットすればaaa
の削除だけでコミットを作れます。
Split into 2 hunks.
@@ -1,6 +1,5 @@
def hello
puts 'Hello'
- aaa
end
def good
(1/3) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y
@@ -4,7 +3,7 @@
end
def good
- puts 'Gooood'
+ puts 'Good'
end
def nice
(2/3) Stage this hunk [y,n,q,a,d,K,j,J,g,/,e,?]? n
@@ -13,3 +12,4 @@ end
hello
good
+nice
(3/3) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? n
同じような手順で他のコミットも作っていけそうですね。
また先ほどはs
で自動分割してましたが、e
を使うと自分で分割することもできます。
❯ git add -p
diff --git a/sample.rb b/sample.rb
index e828f1c..92cd6cb 100644
--- a/sample.rb
+++ b/sample.rb
@@ -1,10 +1,9 @@
def hello
puts 'Hello'
- aaa
end
def good
- puts 'Gooood'
+ puts 'Good'
end
def nice
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,s,e,?]? e
エディタが立ち上がり、手動でインデックスに追加しないコードを選べます。
追加したコード(+の行)はコードを消せば、対象から外れます。
削除したコード(-の行)は-
を
にすれば、対象から外れます。
(実際のファイルは変更されません)
# Manual hunk edit mode -- see bottom for a quick guide.
@@ -1,10 +1,9 @@
def hello
puts 'Hello'
- aaa
end
def good
- puts 'Gooood'
+ puts 'Good'
end
def nice
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging.
# If it does not apply cleanly, you will be given an opportunity to
# edit again. If all lines of the hunk are removed, then the edit is
# aborted and the hunk is left unchanged.
ファイルごとのコミットだけでなく、行単位でコミットが出来そうですね。
まとめ
コミットを細かく分けるためにgit add -p
を使いました。
コミットを細かく分けるメリットは複数ありますが、やはりレビューがしやすいことが一番大きいと思います。
適切に分割されているとレビューワーが見やすくなるので、レビューの精度が上がります。
手間はかかりますが、それよりもメリットの方が大きいので積極的にコミットを分割していきましょう。
References