Interactive Staging 交互式暂存
Git 自带一些脚本,方便你在命令行下进行工作。本节会介绍几个脚本命令,可以让你一次只暂存文件的一部分(正常的暂存只能存整个文件)。比如有时你文件进行了一些改动,但希望将这些改动做成多个提交,以便让一次提交只完成一个任务,这样其他开发者审核起来也比较容易。运行 git add
带选项 -i
或者 --interactive
,Git 会进入一个交互式终端模式:
Git comes with a couple of scripts that make some command-line tasks easier. Here, you’ll look at a few interactive commands that can help you easily craft(制作) your commits to include only certain combinations and parts of files. These tools are very helpful if you modify a bunch of files and then decide that you want those changes to be in several focused commits rather than one big messy commit. This way, you can make sure your commits are logically separate changesets and can be easily reviewed by the developers working with you. If you run git add
with the -i
or --interactive
option, Git goes into an interactive shell mode, displaying something like this:
$ 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: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
Staging and Unstaging Files 暂存与撤销暂存
如果在 What now>
提示符后键入 2 或 u,脚本就会问你想要暂存哪个文件:
What now> 2
staged unstaged path
1: unchanged +0/-1 TODO
2: unchanged +1/-1 index.html
3: unchanged +5/-1 lib/simplegit.rb
Update>>
输入相应的数字就可以了:
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>>
前面的 * 意味文件被选中,再次按回车,选中的文件就会被暂存:
The * next to each file means the file is selected to be staged. If you press Enter after typing nothing at the Update>> prompt, Git takes anything selected and stages it for you:
Update>>
updated 2 paths
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
staged unstaged path
1: +0/-1 nothing TODO
2: +1/-1 nothing index.html
3: unchanged +5/-1 lib/simplegit.rb
如果这时想要撤销对 TODO
文件的暂存,使用 3 或 r(撤消)选项:
What now> 3
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: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
staged unstaged path
1: unchanged +0/-1 TODO
2: +1/-1 nothing index.html
3: unchanged +5/-1 lib/simplegit.rb
使用 6 或 d(区别)命令,类似于 git diff --cached
:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 6
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">
如上所述,用脚本后就不用每次都输入完整的命令了。
Staging Patches 暂存补丁
你也可以只暂存文件的特定部分。例如对 simplegit.rb 文件作了两处修改,但只想暂存其中的一个。这就是 5 或 p(补丁)的功能:(在Git的提示下,一个一个的处理)
It’s also possible for Git to stage certain parts of files and not the rest. For example, if you make two changes to your simplegit.rb file and want to stage one of them and not the other, doing so is very easy in Git. From the interactive prompt, type 5 or p (for patch). Git will ask you which files you would like to partially stage; then, for each section of the selected files, it will display hunks of the file diff and ask if you would like to stage them, one by one:
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
如果你只暂存文件的一部分,状态可能会是下面这样:
Generally, you’ll type y or n if you want to stage each hunk, but staging all of them in certain files or skipping a hunk decision until later can be helpful too. If you stage one part of the file and leave another part unstaged, your status output will look like this:
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
就可以提交已经暂存的内容了。
The status of the simplegit.rb file is interesting. It shows you that a couple of lines are staged and a couple are unstaged. You’ve partially staged this file. At this point, you can exit the interactive adding script and run git commit
to commit the partially staged files.
在命令行中使用 git add
接 -p
或 --patch
选项,也会启动同样的脚本。
You also don’t need to be in interactive add mode to do the partial-file staging – you can start the same script by using git add -p or git add --patch on the command line.
Furthermore, you can use patch mode for partially resetting files with the reset --patch
command, for checking out parts of files with the checkout --patch
command and for stashing parts of files with the stash save --patch
command. We’ll go into more details on each of these as we get to more advanced usages of these commands.