Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【git】git add をインタラクティブに操作する

git add

git addコマンドはコミット対象となるファイルを指定するためのコマンドです。
もっと厳密に言うと、直前のコミット履歴(リビジョン)から現在のファイルの状態(ワーキングツリー)との差分のうち、どの部分を次のコミット履歴の対象とするか(ステージングと呼ぶ)を指定することができます。

通常は以下のようにgit addを利用し、ファイルやディレクトリを指定してステージング行います。

#カレントディレクトリ配下のファイル全てをステージング(.gitignoreで定義されたファイル除く)
$ git add .

# ファイルを指定してステージング
$ git add hoge.txt

インタラクティブにステージング操作を行う

git add -iコマンドを使うことで、以下のようなインタラクティブ操作に切り替わります。

# インタラクティブモード
# stagedはステージングされた変更、unstaged がステージングされていない変更を表す
$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 1 または s(status)を入力してEnterを押すと、上の出力が再度出る
What now> 1
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

ファイルを指定してステージングを行う

2: updateを指定すると、ファイルをステージングできるモードに入ります。

# 2 または u(update)を入力してEnterを押すと、ステージングしたいファイルを選択できる
What now>2
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# ステージングしたいファイルの番号を指定すると、左側に米印がつく
# 米印が付いたファイルは、ステージング対象となる
Update>>1
           staged     unstaged path
* 1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# Enterで確定
Update>>
updated one path

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 終了
What now> q

#ステージング済み
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   hoge1.txt

アンステージングする

3:revertを指定すると、ステージングされたファイルをアンステージすることができます。

$ git add -i
           staged     unstaged path
  1:        +0/-1      nothing hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# revertを選択
What now> 3   
           staged     unstaged path
  1:        +0/-1      nothing hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# アンステージしたいファイルを選択
Revert>> 1
           staged     unstaged path
* 1:        +0/-1      nothing hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# Enterで確定
Revert>> 
reverted one path

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 終了
What now> q
Bye.

# アンステージされている
On branch master
Your branch is up-to-date with 'origin/master'.
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:   hoge1.txt

no changes added to commit (use "git add" and/or "git commit -a")

ラッキングされていないファイルをaddする

4:add untrackedで新規作成したファイルなどの未トラッキング状態のファイルをaddできます。

# 新規作成
$ touch new.txt    

$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 4: add untrackedを選択
# 未トラッキング状態のファイル一覧が表示される
What now> 4
  1: new.txt

# ファイル指定
Add untracked>> 1
* 1: new.txt

# Enterで確定
Add untracked>> 
added one path

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help
What now> q
Bye.

# ステージングされている
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   new.txt

変更箇所を確認しながらaddする

5:patch2:updateと同じようにファイルのステージングを行います。
異なるのは、ハンクと呼ばれる一定行の単位で変更箇所を表示し、各ハンクについてステージングするかどうか訪ねてくる点です。

$ git add -i
           staged     unstaged path
  1:    unchanged        +6/-0 hoge1.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 5:patchを指定
What now> 5
           staged     unstaged path
  1:    unchanged        +6/-0 hoge1.txt

# ファイルを指定
Patch update>> 1
           staged     unstaged path
* 1:    unchanged        +6/-0 hoge1.txt

# Enterで確定
# 確定すると、ハンクをステージングするか訪ねてくる
Patch update>> 
diff --git a/hoge1.txt b/hoge1.txt
index 84ec994..6339dc3 100644
--- a/hoge1.txt
+++ b/hoge1.txt
@@ -1,4 +1,10 @@
+fuga
+
 hoge
 hoge
 piyo
 foo
+hogehoge
+fugafuga
+
+fugafuga

# y でステージング
Stage this hunk [y,n,q,a,d,/,s,e,?]? y

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 終了
What now> q
Bye.

# ステージング済み
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   hoge1.txt

ちなみにこのハンクごとのaddは、git add -pでも行うことができます。
ファイルの部分的なステージングをしたいときにとても重宝します。

$ git add -p
diff --git a/hoge1.txt b/hoge1.txt
index 84ec994..6339dc3 100644
--- a/hoge1.txt
+++ b/hoge1.txt
@@ -1,4 +1,10 @@
+fuga
+
 hoge
 hoge
 piyo
 foo
+hogehoge
+fugafuga
+
+fugafuga
Stage this hunk [y,n,q,a,d,/,s,e,?]? 

ハンクステージング時の操作

ハンクをステージングするときの操作は以下のとおりです。

  • y:表示されたハンクをステージングし、次のハンクへ移る。
  • n:表示されたハンクをステージングせず、次のハンクへ移る。
  • q:終了。まだチェックしていないハンクはすべてアンステージングとなる。
  • a:表示されたハンクをステージングし、同じファイル内の残りのハンクも全部ステージング。
  • d:表示されたハンクをステージングせず、同じファイル内の残りのハンクも全部ステージングしない。
  • g:別のハンクを指定して移動。
  • /:ハンク検索。正規表現もサポート。
  • j:ステージング保留。今のハンクより次にある保留状態のハンクに移動。
  • J:ステージング保留。今のハンクより次にあるハンクに移動。
  • k :ステージング保留。今のハンクより前にある保留状態のハンクに移動。
  • K:ステージング保留。今のハンクより前にあるハンクに移動。
  • s:表示されたハンクをさらに分割したハンクにする。
  • e:エディットモード。表示されたハンクのステージング範囲をエディタで指定する。
  • ?:ヘルプ。