802
744

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GitAdvent Calendar 2012

Day 26

横着で神経質な私とあなたに贈るgit add -p

Last updated at Posted at 2012-12-26

特技はgit commit -a -m いろいろ修正です!

ダメ。ゼッタイ。
しかしこまめにコミットするのは面倒臭いですよね。でもrebaseやらrevertやらcherry-pickするにもコミットログは綺麗にしたい。そんなズボラで凝り性なあなたはgit add -pでコミットを整えるといいと思います。

members
1: 芹沢鴨
2: 原田左之助
3: 藤堂平助
4: 沖田総司
5: 山南敬助

適当な名簿があったとします。ここでは1コミットにつき1行の変更するのが決まりとしましょう。

下のように変更してみました。

-1: 芹沢鴨
+1: 近藤勇
 2: 原田左之助
 3: 藤堂平助
 4: 沖田総司
-5: 山南敬助
+5: 土方歳三

さてこのままgit addすると両方の変更が一度にステージングされてしまいます。
そこでgit add -pすると以下のようなdiffがコンソールに表示されます。

console
diff --git a/members b/members
index 15440ce..1f43716 100644
--- a/members
+++ b/members
@@ -1,5 +1,5 @@
-1: 芹沢鴨
+1: 近藤勇
 2: 原田左之助
 3: 藤堂平助
 4: 沖田総司
-5: 山南敬助
+5: 土方歳三
Stage this hunk [y,n,q,a,d,s,e,?]?  

変更のひとかたまり(ハンク)を表示し、そのハンクに対しての指示を待ち受けます。サンプルが小さいのですべて表示されますが、ハンクの間が7行以上空くと別のハンクとして扱われます。

変更を分割する

コミットを分割するのが目的なのでここでsを入力します。

console
Split into 2 hunks.
@@ -1,4 +1,4 @@
-1: 芹沢鴨
+1: 近藤勇
 2: 原田左之助
 3: 藤堂平助
 4: 沖田総司
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? 

するとハンクが2つに分割され、diffの表示される範囲が狭まり一人だけの変更になりました。yでこの変更をステージングしましょう。
さらに次のハンクが表示されステージングするか否か選べますがひとまずnでスキップするかqで終了します。

git-status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   members
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   members
#

git statusを見るとmembersステージされているにもかかわらずワークスペースに残った状態になってますね。
ここでgit diffを見ると

git-diff
@@ -2,4 +2,4 @@
 2: 原田左之助
 3: 藤堂平助
 4: 沖田総司
-5: 山南敬助
+5: 土方歳三

最終行の変更だけが残っています。
そしてステージングされた状態を確認するためにgit diff --cachedすると

git-diff-cached
@@ -1,4 +1,4 @@
-1: 芹沢鴨
+1: 近藤勇
 2: 原田左之助
 3: 藤堂平助
 4: 沖田総司

先頭の変更だけがステージングされていますね。
これで1つの変更だけどコミットすることができます。

さらに分割する

ハンク同士が1行以上空いている場合はsで分割できますが、連続する行の場合はそうはいきません。

console
@@ -1,5 +1,5 @@
 1: 芹沢鴨
-2: 原田左之助
-3: 藤堂平助
+2: 斎藤一
+3: 永倉新八
 4: 沖田総司
 5: 山南敬助
Stage this hunk [y,n,q,a,d,/,e,?]? 

このように変更した行が連続する場合sが使えません。もしこの状態を分割したい場合はeで直接編集する必要があります。

edit
# Manual hunk edit mode -- see bottom for a quick guide
@@ -1,5 +1,5 @@
 1: 芹沢鴨
-2: 原田左之助
-3: 藤堂平助
+2: 斎藤一
+3: 永倉新八
 4: 沖田総司
 5: 山南敬助
# ---
# 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.

eを押すとエディタが立ち上がり、diffの編集画面になります。元の状態からの差分を記述することでその変更を適用することができます。

edit/2行目だけを適用する場合
# Manual hunk edit mode -- see bottom for a quick guide
@@ -1,5 +1,5 @@
 1: 芹沢鴨
-2: 原田左之助
+2: 斎藤一
 3: 藤堂平助
 4: 沖田総司
 5: 山南敬助
# ---
# 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.

上記のように内容を変更し保存するとステージングとして適用されます。ちなみにdiffとして正しければ何を書いてもいいのでこの画面で変更をさらに変更することもできます。フォーマットがおかしかったり差分が解決できない場合はステージングされません。

git-diff-cached
@@ -1,5 +1,5 @@
 1: 芹沢鴨
-2: 原田左之助
+2: 斎藤一
 3: 藤堂平助
 4: 沖田総司
 5: 山南敬助

これで連続した行の変更を分割してステージングすることができました。

これで綺麗なコミットログがつくれるね!

とは言うものの変更が増えた後にいちいちハンクを分割してコミットだのやってられないので作業のスコープをちゃんとしぼってこまめにコミットしたほうがいいと思います。ちなみに僕の特技はgit commit -a -m いろいろ修正です!

おまけ:git add -pした時のコマンド一覧

  • y - このハンクをステージングする
  • n - スキップする
  • q - 終了する
  • a - 以降のハンクをすべてステージングする
  • d - 以降のハンクをすべてスキップする
  • g - 指定したハンクへ移動
  • / - 正規表現によるハンクの検索
  • j - 未確定な次のハンクへ移動する
  • J - 次のハンクへ移動する
  • k - 未確定な前のハンクへ移動する
  • K - 前のハンクへ移動する
  • s - ハンクを分割する
  • e - 手動で現在のハンクを修正する
  • ? - ヘルプを表示する
802
744
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
802
744

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?