git add -p 使ってますか？

皆さん、git であるコードの一部分だけコミットしたいとか
ありませんか？

私は時々あります。

commit するの忘れてて、別の機能に取り掛かった時になど。
そんなときはgit add -p 使いましょう。

で、頻度が低いせいか毎回 git add のなんだっけ？ とか
git add -p のなんだっけ？と苦労してます。

それも google 先生で git add -p で検索しても
一発でヒットしないからです。

なのでオレオレメモとして残そうと思います。

まずはおさらいとして git add とは？

```
git add <file名>
```

git add をすることによって選択されたファイルが
stage済またはコミット対象ファイルとなります。 

さて、git add -p とは？

```
git add -p <file名>
```

上記のコマンドを実行するとgitが更新した内容について
任意のブロックに分割して、その任意のブロック毎に対して
どうするのかを以下の選択肢から選択することができます。
選択肢から選んでEnterを押下します。

```
Stage this hunk [y,n,q,a,d,/,e,?]
```

y なら任意のブロックをgit addをする (stage済)
n なら任意のブロックをスキップする
などです。

表示されてない選択肢も含めて選択可能な操作一覧は以下です。
(? を選択すると以下の操作一覧が表示されます。)

```
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
```

英語が得意な皆さんならもうなんとなくわかったんじゃないでしょうか。

自分用のメモとして残そうとしたのは s , e の使い方です。

s なら任意のブロックを更に細かいブロックに分割する
e は自分でgit add の対象となるブロックを指定する
そのため、s にて上手く分割されない時にe を使います。

e について例を使って説明します。
例えば以下のようファイルがあるとします。

状態としては空のHokurikuCommunityGroups.txtを
git addしてある状態です。

```
git add HokurikuCommunityGroups.txt
```

その後に以下のコミュニティを追記しました。

```HokurikuCommunityGroups.txt
ふくもく会
Hokuriku.NET
JAWS-UG金沢
kanazawa.rb
toyama.rb
WDF(Web Directors Forum)
```

まずはふくもく会だけコミットした場合

```
git add -p HokurikuCommunityGroups.txt
diff --git a/HokurikuCommunityGroups.txt b/HokurikuCommunityGroups.txt
index e69de29..f385ec8 100644
--- a/HokurikuCommunityGroups.txt
+++ b/HokurikuCommunityGroups.txt
@@ -0,0 +1,6 @@
+ふくもく会
+Hokuriku.NET
+JAWS-UG金沢
+kanazawa.rb
+toyama.rb
+WDF(Web Directors Forum)
Stage this hunk [y,n,q,a,d,/,e,?]? e
```

e を入力後Enterを押下すると、vim/vi が開かれます。

```
# Manual hunk edit mode -- see bottom for a quick guide
@@ -0,0 +1,6 @@
+ふくもく会
+Hokuriku.NET
+JAWS-UG金沢
+kanazawa.rb
+toyama.rb
+WDF(Web Directors Forum)
# ---
# 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.
```

上記のような表示がされますので以下のように
ふくもく会以外を削除します。

```
# Manual hunk edit mode -- see bottom for a quick guide
@@ -0,0 +1,6 @@
+ふくもく会
# ---
# 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.
```

因みに以下のようにヘッダー、フッターを削除しても大丈夫です。

```
+ふくもく会
```

で :wq で保存します。
**** 注意 ****
誤って、e にてvim/vi を開いてしまった場合は
+行、または-行を削除してエディタを閉じないと
全てgit add されてしまいます。
私の場合は :q または :q! でも全て
git add されてしまいました。
** 

確認として再度 git add -p を実行します。

```
git add -p HokurikuCommunityGroups.txt
diff --git a/HokurikuCommunityGroups.txt b/HokurikuCommunityGroups.txt
index a785f45..f385ec8 100644
--- a/HokurikuCommunityGroups.txt
+++ b/HokurikuCommunityGroups.txt
@@ -1 +1,6 @@
 ふくもく会
+Hokuriku.NET
+JAWS-UG金沢
+kanazawa.rb
+toyama.rb
+WDF(Web Directors Forum)
```

ふくもく会だけが git add されていることが確認できます。
git status にて更新した内容が全てgit addされてないことが
確認できます。

```
git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   HokurikuCommunityGroups.txt

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:   HokurikuCommunityGroups.txt
```

後はcommitするだけです。
git add -p を使うことによって一部分のみをコミット対象とすることができます。

#所感
これで google 先生で git add -p を検索したら一発でヒットしてくれると
私の作業効率が今よりもちょっと上がるんだけどな〜。