[注意:评论变成答案 - 顶部是你所需要的,其余的只是解释]
补丁块所做的唯一更改是添加那一行。如果把添加的行去掉,patch就变成了一个指令,通过不改变文件来改变文件,这不是很明智。这里的错误消息有点傻,但您需要的操作只是“跳过这个”。
很多细节,只有感兴趣的时候才能阅读
请注意,在您进行下一次提交时,始终存在三个我称之为每个文件的活动副本。好吧,更准确地说,最多有三个这样的副本。第一个是您之前提交的任何内容,或者在您运行时获得的提交中包含的内容git checkout
。该副本存储在提交中,基本上是只读的:您无法更改它,因为它是该特定提交的一部分。但是您可以随时访问它。例如,给定一个README.txt
文件,您可以运行:
git show HEAD:README.txt
查看它。在内部,这个文件以一种特殊的 Git-only 格式存储(zlib-deflate,甚至可能进一步压缩)——非 Git 程序通常无法读取该文件的副本。
在您的work-tree中也有相同文件的副本,您可以在其中处理它。此副本以其普通计算机格式存储,以便您阅读。你的编辑器——atom 或 emacs 或 sublime 或 vim 或任何你使用的——可以读写文件。你的编译器,如果你编译程序,可以读写它,等等。您无需对该文件做任何特殊处理,因为它与任何其他文件一样。奇怪的是,Git几乎不关心这个副本README.txt
——Git 必须不干涉,因为任何事情都可以改变它!
但是也有第三个副本,README.txt
这就是 Git 所称的那个,不同的是,index,或staging area,或cache。(Git 使用哪个名称取决于您正在查看的 Git 文档。)您可以使用 看到的第三个副本采用git show :README.txt
特殊的 Git-only 格式,但与commit中的副本不同,您可以覆盖这个副本。覆盖此文件的常用方法是使用git add
,它只是将工作树文件复制到索引中。
因此,索引:README.txt
开始匹配HEAD:README.txt
文件。如果您更改工作树副本,HEAD 和索引版本仍然匹配。如果你 then git add README.txt
,那将覆盖工作树副本中的索引副本,并且现在HEAD:README.txt
不再README.txt
匹配,但:README.txt
确实匹配README.txt
。
这就是git add -p
进来的地方:如果某个文件的索引副本和工作树副本不同,您可以让 Git 提供一个补丁——一组大块,每个都说添加和/或删除某些行或行——如果应用,将更改索引版本以匹配工作树版本。如果 Git 遵循补丁中的所有说明,那将更改文件的索引副本以匹配工作树副本,就像这样git add
做一样。
但是现在 Git 让你通过那个补丁,一次一个补丁块,并且:
- 告诉 Git 按原样应用它;或者
- 告诉 Git 完全跳过它;甚至
- 摆弄更改说明以部分应用补丁。
当您选择应用特定的补丁块时(可能在编辑后),Git 会提取文件的索引版本,应用该组指令,然后继续查看下一个。如果你跳过它,Git 就会继续下一个。
请注意,有一个git add -p
:runninggit reset -p README.txt
告诉 Git 它应该比较HEAD:README.txt
和:README.txt
(HEAD 和索引版本),并准备一个补丁,如果按照字母顺序更改索引副本,以便它HEAD
再次匹配副本。然后 Git 经历与 for 相同的过程git add -p
。
最后,让我们快速浏览一下git status
。这做了很多有用的事情,但它告诉您关于为提交暂存的更改和未为提交暂存的更改的内容实际上包括运行两个git diff
命令。第一个是:
对于此处完全相同的每个文件,Git 对此保持沉默。但是如果HEAD:README.txt
和不同, Git:README.txt
会告诉你在.README.txt
列出所有这些文件后,Git 运行第二个 diff,这次是为了找出:
在这里,任何不同的文件,Git 都会告诉你有一些东西没有为 commit 暂存。那是因为您可以在该文件上运行git add
,将其复制到索引中。
如果你git commit
现在运行,Git 会从现在索引中的任何内容进行新的提交,所以-vs-index 告诉你:在这个新提交中,这些文件与当前提交中的文件会有所不同。 同时 index-vs-work-tree 告诉你:这些文件可能不同,但除非你是它们,否则它们不会不同。HEAD
git add
这第二个差异也是发现任何未跟踪文件的步骤。很简单,未跟踪的文件是工作树中的文件,但不在索引中。如果这样的文件被忽略,Git 就会关闭它。如果未跟踪的文件没有被忽略,Git 会告诉你它是未跟踪的。请注意,根据定义跟踪索引中的文件,因此 Git 甚至从不检查忽略指令。
这个事实——关于新的/未跟踪的文件——是每个文件最多有三个副本的原因。如果您创建一个新文件,它根本不在HEAD
提交中。git add
在您将文件复制到索引中之前,它也是未跟踪的。因此,您从一个副本开始,仅在工作树中;那么你有两个,在索引和工作树中。然后你做出一个新的提交,它变成了当前的 ( HEAD
) 提交,只有这样才会有那个新文件的三个副本。