章 ▾ 第2版

7.2 Gitツール - 対話型ステージング

対話型ステージング

このセクションでは、ファイルの特定の部分だけをコミットに含めるようにコミットを作成するのに役立つ、いくつかの対話型Gitコマンドを見ていきます。これらのツールは、多数のファイルを広範囲にわたって変更し、それらの変更を一つの大きな雑然としたコミットではなく、いくつかの焦点を絞ったコミットに分割したい場合に役立ちます。このようにすることで、コミットが論理的に分離された変更セットとなり、共同作業を行う開発者によって簡単にレビューされることを保証できます。

git addコマンドを-iまたは--interactiveオプションで実行すると、Gitは対話型シェルモードに入り、次のような表示をします

$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:    unchanged        +1/-1 index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now>

このコマンドは、おそらく慣れているgit statusで得られる情報と基本的に同じですが、より簡潔で情報量の多いステージングエリアのビューを表示します。左側にはステージされた変更が、右側にはステージされていない変更がリストされます。

その後に「Commands(コマンド)」セクションがあり、ファイルのステージングやステージ解除、ファイルの一部をステージング、追跡されていないファイルの追加、ステージされた差分の表示など、様々なことができます。

ファイルのステージングとステージ解除

What now>プロンプトでuまたは2(updateの場合)と入力すると、どのファイルをステージしたいか尋ねられます

What now> u
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:    unchanged        +1/-1 index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Update>>

TODOファイルとindex.htmlファイルをステージするには、数字を入力します

Update>> 1,2
           staged     unstaged path
* 1:    unchanged        +0/-1 TODO
* 2:    unchanged        +1/-1 index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Update>>

各ファイルの隣にある*は、そのファイルがステージ対象として選択されていることを意味します。Update>>プロンプトで何も入力せずにEnterを押すと、Gitは選択されたものをすべてステージします

Update>>
updated 2 paths

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> s
           staged     unstaged path
  1:        +0/-1      nothing TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

これで、TODOファイルとindex.htmlファイルがステージされ、simplegit.rbファイルはまだステージされていないことがわかります。この時点でTODOファイルをステージ解除したい場合は、rまたは3(revertの場合)オプションを使用します

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +0/-1      nothing TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Revert>> 1
           staged     unstaged path
* 1:        +0/-1      nothing TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Revert>> [enter]
reverted one path

もう一度Gitの状態を見ると、TODOファイルがステージ解除されていることがわかります

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> s
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

ステージされた差分を確認するには、dまたは6(diffの場合)コマンドを使用します。これにより、ステージされたファイルの一覧が表示され、ステージされた差分を見たいファイルを選択できます。これはコマンドラインでgit diff --cachedを指定するのとよく似ています

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> d
           staged     unstaged path
  1:        +1/-1      nothing index.html
Review diff>> 1
diff --git a/index.html b/index.html
index 4d07108..4335f49 100644
--- a/index.html
+++ b/index.html
@@ -16,7 +16,7 @@ Date Finder

 <p id="out">...</p>

-<div id="footer">contact : support@github.com</div>
+<div id="footer">contact : email.support@github.com</div>

 <script type="text/javascript">

これらの基本的なコマンドを使えば、対話型追加モードでステージングエリアをより簡単に扱うことができます。

パッチのステージング

Gitでは、ファイルの一部のみをステージし、残りをステージしないことも可能です。たとえば、simplegit.rbファイルに2つの変更を加え、そのうちの1つだけをステージし、もう1つをステージしたくない場合、Gitでは非常に簡単に行えます。前のセクションで説明した対話型プロンプトから、pまたは5(patchの場合)と入力します。Gitは、どのファイルを部分的にステージしたいか尋ね、その後、選択されたファイルの各セクションについて、ファイル差分のハンクを表示し、それらを1つずつステージするかどうか尋ねます

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..57399e0 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -22,7 +22,7 @@ class SimpleGit
   end

   def log(treeish = 'master')
-    command("git log -n 25 #{treeish}")
+    command("git log -n 30 #{treeish}")
   end

   def blame(path)
Stage this hunk [y,n,a,d,/,j,J,g,e,?]?

この時点で多くのオプションがあります。?と入力すると、できることのリストが表示されます

Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ?
y - stage this hunk
n - do not stage this hunk
a - stage this and all the remaining hunks in the file
d - do not stage this hunk nor any of the remaining 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と入力しますが、特定のファイル内のすべてのハンクをステージしたり、ハンクの決定を後回しにしたりすることも役立ちます。ファイルの一部をステージし、別の部分をステージしないままにした場合、ステータス出力は次のようになります

What now> 1
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:        +1/-1      nothing index.html
  3:        +1/-1        +4/-0 lib/simplegit.rb

simplegit.rbファイルのステータスは興味深いものです。数行がステージされ、数行がステージされていないことを示しています。このファイルを部分的にステージしたことになります。この時点で、対話型追加スクリプトを終了し、git commitを実行して部分的にステージされたファイルをコミットできます。

また、ファイルの部分的なステージングを行うために、対話型追加モードである必要はありません。コマンドラインでgit add -pまたはgit add --patchを使用することで、同じスクリプトを開始できます。

さらに、git reset --patchコマンドでファイルの一部をリセットしたり、git checkout --patchコマンドでファイルの一部をチェックアウトしたり、git stash save --patchコマンドでファイルの一部を一時保存したりするのにパッチモードを使用できます。これらのコマンドのより高度な使用法に到達するにつれて、それぞれの詳細を説明していきます。

scroll-to-top