章节 ▾ 第二版

7.2 Git 工具 - 交互式暂存

交互式暂存

在本节中,你将了解一些交互式 Git 命令,它们可以帮助你精心组织提交,使其只包含特定文件组合和文件部分。如果你对大量文件进行了大量修改,然后决定将这些更改划分为多个重点突出的提交,而不是一个庞大而混乱的提交,那么这些工具会很有帮助。这样,你就可以确保你的提交是逻辑上独立的一组更改,并且可以轻松地被与你合作的开发人员审查。

如果你运行带 -i--interactive 选项的 git add 命令,Git 会进入交互式 Shell 模式,显示如下内容:

$ 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 相同的信息,但更简洁、更具信息量。它在左侧列出了已暂存的更改,在右侧列出了未暂存的更改。

接下来是“命令”部分,它允许你执行多项操作,例如暂存和取消暂存文件、暂存文件的一部分、添加未跟踪文件以及显示已暂存内容的差异。

暂存和取消暂存文件

如果你在 What now> 提示符处键入 u2 (表示更新),系统会提示你选择要暂存的文件:

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

要暂存 TODOindex.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

现在你可以看到 TODOindex.html 文件已暂存,而 simplegit.rb 文件仍未暂存。如果你想此时取消暂存 TODO 文件,可以使用 r3 (表示恢复) 选项:

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

要查看已暂存内容的差异,你可以使用 d6 (表示差异) 命令。它会显示你已暂存的文件列表,你可以选择要查看已暂存差异的文件。这与在命令行中指定 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 文件进行了两处修改,并希望只暂存其中一处而保留另一处不暂存,这在 Git 中非常容易实现。在上一节中解释过的同一个交互式提示符下,键入 p5 (表示补丁)。Git 会询问你希望部分暂存哪些文件;然后,对于所选文件的每个部分,它会显示文件差异的“hunk”(块),并逐一询问你是否希望暂存它们:

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

通常,如果你想暂存每个 hunk,你会键入 yn,但一次性暂存某些文件中的所有 hunk,或者将某个 hunk 的决定推迟到以后再做,也可能会很有帮助。如果你暂存了文件的一部分而将另一部分保留为未暂存状态,你的状态输出将如下所示:

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 -pgit add --patch 来启动相同的脚本。

此外,你可以使用补丁模式通过 git reset --patch 命令部分重置文件,通过 git checkout --patch 命令检出文件部分,以及通过 git stash save --patch 命令暂存文件部分。当我们介绍这些命令的更高级用法时,我们将详细讲解每一种用法。

scroll-to-top