Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

特技は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 - 手動で現在のハンクを修正する
  • ? - ヘルプを表示する
crifff
最近はgoとかappengineが世界を救うと信じてる
bandainamcostudios
バンダイナムコスタジオは、家庭用ゲームソフト、モバイルコンテンツ、の企画・開発・運営、ゲームに関する技術研究・開発を行っている会社です。
https://www.bandainamcostudios.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away