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