git stash -p
应该在Git 2.17(2018年第二季度)上减少失败。
在此之前,“ git add -p
(与共享逻辑git stash
)”在将结果传递给底层的“ git apply
”之前一直懒于合并拆分补丁,从而导致极端的案例错误;紧缩选择之后准备要应用的补丁的逻辑。
参见commit 3a8522f,commit b3e0fcfPhillip Wood()的,提交2b8ea7f(2018年3月5日),提交fecc6f3,提交23fea4c,提交902f414(2018年3月1日)和提交11489a6,提交e4d671c,提交492e60c(2018年2月19日)。(通过合并JUNIOÇ滨野- -在提交436d18f,2018年3月14日)phillipwood
gitster
add -p
:跳过一个后的块的偏移量
(添加,但同样可以应用于隐藏)
由于提交8cbd431(“ git-add--interactive
:用apply --recount替换大块重计”,2008-7-2,Git v1.6.0-rc0)如果大块被跳过,则我们依赖上下文行在正确的位置应用后续大块。
尽管大多数情况下这都是可行的,但很可能最终将块应用在错误的位置。
要解决此问题,请调整后续块的偏移量,以纠正由于跳过的块导致的插入或删除次数的任何变化。由于编辑的块改变了插入或删除的数量而导致的偏移量更改在此处被忽略,它将在下一次提交中修复。
您可以在此处看到一些测试。
Git 2.19进行了改进git add -p
:当用户在“ git add -p
”中编辑补丁,并且用户的编辑器设置为不加区分地去除尾随空白时,补丁中未更改的空行将变为完全空(而不是上面带有唯一SP的行)。
Git 2.17时间框架中引入的代码未能解析此类补丁,但是现在它学会了注意情况并加以解决。
参见Phillip Wood()的commit f4d35a6(2018年6月11日)。(通过合并JUNIOÇ滨野- -在提交5eb8da8 6月28日2018)phillipwood
gitster
add -p
:修复了对已编辑补丁中的空白上下文行进行计数的问题
recount_edited_hunk()
在commit 2b8ea7f中引入(“ add -p:计算已编辑补丁的偏移量增量”,2018-03-05,Git v2.17.0)要求所有上下文行以空格开头,不计算空行。
如果用户在编辑补丁时在末尾引入了空行,则可以避免重新计数的问题。
但是,这将回归引入到' git add -p
'中,这似乎是编辑人员在编辑补丁时从空白上下文行中删除尾随空白,从而引入应计数的空白行的常见现象。
'git apply'知道如何处理这些空行,并且POSIX指出在空上下文行上是否有空格是实现定义的(请参见diff命令)。
通过对仅包含换行符的行以及以空格开头的行作为上下文行进行计数来修复回归,并添加测试以防止将来回归。
Git 2.23(Q3 2019)改进了git add -p
“ git checkout -p
”所使用的,它需要有选择地反向应用补丁:之前效果不佳。
参见Phillip Wood()的commit 2bd69b9(2019年6月12日)。phillipwood
(由Junio C gitster
Hamano合并--在commit 1b074e1中,2019年7月9日)
add -p
:checkout -p
配合病理背景
提交fecc6f3(“ add -p
:跳过时,调整后续块的偏移量”,2018-03-01,Git v2.17.0-rc0)已修复在跳过前一个块时将块添加到正确位置的问题。
但是,它没有解决反向应用的补丁。
在这种情况下,我们需要调整图像前偏移,以便当应用反转贴片时,可以正确调整图像后偏移。
当补丁反转时,我们减去而不是增加增量(考虑它的最简单方法是考虑被跳过的大量删除-在这种情况下,我们要减少偏移量,因此我们需要减去)。
在Git 2.25(2020年第一季度)中,继续将git-add--interactive
Perl脚本移至C的工作。
结果,上述修复程序得以重新实现。
见提交2e40831,提交54d9d9b,提交ade246e,提交d6cf873,提交9254bdf,提交bcdd297,提交b38dd9e,提交11f2c0d,提交510aeca,提交0ecd9d2,提交5906d5d,提交47dc4fd,提交80399ae,提交7584dd3,提交12c24cf,提交25ea47a,提交e3bd11b,提交1942ee4,提交f6aa7ec(13 Dec 2019)通过Johannes Schindelin(dscho
)。
(由Junio C gitster
Hamano合并--在commit 45b96a6中,2019年12月25日)
签字人:约翰内斯·辛德尔林
跳过添加的行数与删除的行数不同的块时,我们需要调整未跳过的块的后续块头:在病理情况下,上下文不足以精确确定应在何处应用补丁。
在23fea4c240中发现了此问题(“ t3701
:add
病理上下文线测试失败”,2018-03-01,Git v2.17.0-rc0- merge),并在fecc6f3a68的Perl版本中修复了该问题(“ add -p
:一个被跳过“,2018-03-01,Git v2.17.0-rc0- merge)。
这个补丁可以在C的C版本中修复它git add -p
。
与Perl版本相反,我们尝试保持多余的文本在块头(通常包含其代码在块中更改的函数的签名)上。
注意:虽然C版本在此阶段不支持登台模式更改,但我们已经为此做好了准备,只需在新旧偏移量均为0时跳过大块头(对于常规大块就不会发生,我们将其用作表示我们正在查看特殊块)。
同样,我们已经通过适当地处理大块标题中缺少多余文本的方式来准备大块拆分:只有第一个拆分大块具有该文本,而其他大块没有(通过空的额外文本开始/结束范围来表示)。在这个阶段已经准备好进行块分割,可以避免以后整个块头打印块的缩进更改,并且几乎像没有处理那样容易进行检查。
在Git 2.27(2020年第二季度)之前,允许用户在“git stash -p
”不能很好地工作;添加了创可贴,以使其(部分)更好地工作。
参见Johannes Schindelin()的提交7723436和提交121c0d4(2020年4月8日)。(由Junio C Hamano合并--在e81ecff提交中,2020年4月28日)dscho
gitster
stash -p
:(部分)修复有关拆分大块头的错误
签字人:约翰内斯·辛德尔林
当试图通过拆分块来隐藏工作树的部分更改,然后仅部分接受拆分后的片段时,会向用户显示一个相当神秘的错误:
error: patch failed: <file>:<line>
error: test: patch does not apply
Cannot remove worktree changes
并且该命令将无法隐藏工作树更改的所需部分(即使stash
参考实际上已正确更新)。
我们甚至有一个测试案例证明了这种失败,已经持续了四年。
解释:分割大块时,更改的行不再被多于3行(这是默认情况下Git的diff使用的上下文行的数量)隔开,但小于此值。
因此,当仅暂存部分diff块进行存储时,我们想要反向应用于工作树的结果diff将包含那些要删除的更改,并由三个上下文行包围,但是由于diff是相对于HEAD而不是相对于HEAD工作树,这些上下文行将不匹配。
时间示例。假设文件README包含以下几行:
We
the
people
并且工作树添加了一些行,以便包含这些行:
We
are
the
kind
people
并且用户尝试隐藏包含“ are”的行,那么该命令将在内部将此行暂存为临时索引文件,并尝试还原HEAD与该索引文件之间的差异。尝试还原
的diff块git stash
看起来像这样:
@@ -1776,3 +1776,4
We
+are
the
people
很明显,现在,这后上下文行与原来差异大块用户也部分重叠,不希望藏匿。
请记住,差异中的上下文行主要用于找到差异不完全适用时的确切位置(但当要打补丁的文件中的确切行号与差异中指示的行号不同时),我们可以通过减少上下文行的数量来解决此问题:仅生成差异。
注意:这不是此问题的完整解决方案。
就像在t3701的“ add -p与病理上下文线一起工作”测试用例中所证明的那样,diff格式中存在歧义。当然,在实践中很少会遇到这种重复的现象。
对于这种情况,完整的解决方案将是替换从存储中生成差异然后通过仿真git revert
(即进行三向合并)反向应用差异的方法。但是,git stash -p
它不适用于工作HEAD
树,而只适用于工作树,只要我们还维护的脚本版本,这将使实现这个工作很简单add -i
。
Git 2.29(Q4 2020)为git add -p
(由...使用stash -p
)
参见Phillip Wood()提交的324efcf(2020年9月7日)。(由Junio C Hamano合并--在commit 3ad8d3e中,2020年9月18日)phillipwood
gitster
签名人:Phillip Wood
签名人:Johannes Schindelin
asan报告说C版本的 add -p
没有释放它分配的所有内存。
通过引入清除struct
add_p_state的函数并使用它而不是释放单个成员来解决此问题。