为什么 `git stash -p` 有时会失败?
我♥git stash -p
。但有时,在一次令人满意的 y、n 和 s 会话之后,我会明白:
Saved working directory and index state WIP on foo: 9794c1a lorum ipsum
error: patch failed: spec/models/thing_spec.rb:65
error: spec/models/thing_spec.rb: patch does not apply
Cannot remove worktree changes
为什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
每当我尝试将一个大块拆分为距离太近的较小块(更改之间的行数少于 3 行)时,这种情况就会发生在我身上。简而言之,该补丁中的上下文行与您的本地更改发生冲突。下面有更完整的解释。
假设我有一个包含这些未提交更改的 git 存储库:
如果我存储第一个更改,我会得到:
git stash 命令实际上确实成功保存了补丁(检查 git stash list ) >),但随后 git 反向使用该补丁来删除我的工作目录中隐藏的更改。大块头之后的上下文有“跳跃”,这与仍在我的工作目录中的“行走”不匹配。因此 git 会放弃
并将所有更改保留在我的工作目录中,并且存储变得几乎毫无价值。
我认为这是 git 块分割支持中的一个错误。如果它知道它把更改分割得太近,它可能会从补丁中删除几行上下文,或者吉米补丁以获得修改后的上下文行而不是原始的上下文行。或者,如果官方不支持如此接近的分裂帅哥,那么它实际上应该拒绝如此接近的分裂帅哥。
This happens for me any time I try to split a hunk into smaller hunks that are too close together (less than 3 lines between changes). The short explanation is that the patch has context lines in it that conflict with your local changes. More complete explanation below.
Suppose I have a git repo with these uncommitted changes:
If I stash the first change, I get:
The
git stash
command actually does succeed in saving the patch (checkgit stash list
), but then git uses that patch in reverse to remove the stashed changes from my working dir. The context after the hunk has "jumps", which doesn't match the "walks" still in my working dir. So git bails out withand leaves all the changes in my working dir, and the stash becomes pretty much worthless.
I would call this a bug in git's hunk splitting support. If it knows it's splitting the changes too close, it could shave off a few lines of context from the patch, or jimmy the patch to have the modified context lines instead of the pristine ones. Alternatively, if splitting hunks this close is officially unsupported, it should actually refuse to split hunks that close.
git stash -p
使用 Git 2.17(2018 年第 2 季度)应该会减少失败。在此之前,“
git add -p
”(与git stash
共享逻辑)在将结果传递给底层“git apply”之前一直懒于合并分割补丁。
”,导致极端情况错误;在大块选择之后准备要应用的补丁的逻辑已经收紧。请参阅 提交 3a8522f、提交 b3e0fcf, 提交 2b8ea7f(2018 年 3 月 5 日),提交 fecc6f3,提交 23fea4c,提交 902f414(2018 年 3 月 1 日),以及提交 11489a6, 提交 e4d671c,提交 492e60c(2018 年 2 月 19 日),作者:Phillip Wood (
菲利普伍德
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 436d18f,2018 年 3 月 14 日)(添加,但同样可以应用于存储)
您可以在此处查看一些测试。
Git 2.19 改进了
git add -p
:当用户在“git add -p
”中编辑补丁并且用户的编辑器设置为不加区别地去除尾随空格时,会出现一个空行补丁中未更改的内容将变得完全空(而不是带有唯一 SP 的行)。Git 2.17 时间范围中引入的代码无法解析这样的补丁,但现在它学会了注意到这种情况并应对它。
请参阅 提交 f4d35a6(2018 年 6 月 11 日),作者:菲利普·伍德 (
phillipwood
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 5eb8da8,2018 年 6 月 28 日)Git 2.23(2019 年第 3 季度)改进了“
git checkout -p
”使用的git add -p
,它需要选择性地反向应用补丁:效果不佳前。请参阅 提交 2bd69b9(2019 年 6 月 12 日),作者:菲利普·伍德 (
phillipwood
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 1b074e1,2019 年 7 月 9 日)在 Git 2.25(2020 年第一季度)中,将“
git-add--interactive
”Perl 脚本移至 C 的工作仍在继续。因此,重新实施了上述修复。
请参阅 提交 2e40831、提交 54d9d9b, 提交 ade246e、提交 d6cf873、提交 9254bdf, 提交 b38dd9e,提交 11f2c0d, 提交 510aeca,提交 0ecd9d2,提交 5906d5d,提交 47dc4fd,提交 80399ae,提交7584dd3,提交 25ea47a,提交 e3bd11b, 提交 1942ee4、提交 f6aa7ec(2019 年 12 月 13 日) )作者:Johannes Schindelin (
dscho
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 45b96a6,2019 年 12 月 25 日)在 Git 2.27(2020 年第 2 季度)之前,允许用户拆分补丁块,而“
git stash -p
”效果不佳;添加了创可贴以使其(部分)发挥更好的作用。请参阅 提交 7723436、提交 121c0d4(2020 年 4 月 8 日),作者:Johannes Schindelin (
dscho
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 e81ecff,2020 年 4 月 28 日)Git 2.29(2020 年第 4 季度)为
git add -p
(由stash -p
使用)带来了泄漏修复,请参阅 提交 324efcf(2020 年 9 月 7 日),作者:Phillip Wood (<代码>菲利普伍德)。
(由 Junio C Hamano --
gitster
-- 合并于 提交 3ad8d3e,2020 年 9 月 18 日)git stash -p
should fail less with Git 2.17 (Q2 2018).Before that, "
git add -p
" (which shares logic withgit stash
) has been lazy in coalescing split patches before passing the result to underlying "git apply
", leading to corner case bugs; the logic to prepare the patch to be applied after hunk selections has been tightened.See commit 3a8522f, commit b3e0fcf, commit 2b8ea7f (05 Mar 2018), commit fecc6f3, commit 23fea4c, commit 902f414 (01 Mar 2018), and commit 11489a6, commit e4d671c, commit 492e60c (19 Feb 2018) by Phillip Wood (
phillipwood
).(Merged by Junio C Hamano --
gitster
-- in commit 436d18f, 14 Mar 2018)(add, but again, can be applied to stash)
You can see some tests here.
Git 2.19 improves
git add -p
: when user edits the patch in "git add -p
" and the user's editor is set to strip trailing whitespaces indiscriminately, an empty line that is unchanged in the patch would become completely empty (instead of a line with a sole SP on it).The code introduced in Git 2.17 timeframe failed to parse such a patch, but now it learned to notice the situation and cope with it.
See commit f4d35a6 (11 Jun 2018) by Phillip Wood (
phillipwood
).(Merged by Junio C Hamano --
gitster
-- in commit 5eb8da8, 28 Jun 2018)Git 2.23 (Q3 2019) improves the
git add -p
, used by "git checkout -p
" which needs to selectively apply a patch in reverse: it did not work well before.See commit 2bd69b9 (12 Jun 2019) by Phillip Wood (
phillipwood
).(Merged by Junio C Hamano --
gitster
-- in commit 1b074e1, 09 Jul 2019)With Git 2.25 (Q1 2020), The effort to move "
git-add--interactive
" Perl script to C continues.As a result, the fixes mentioned above are re-implemented.
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, commit 1942ee4, commit f6aa7ec (13 Dec 2019) by Johannes Schindelin (
dscho
).(Merged by Junio C Hamano --
gitster
-- in commit 45b96a6, 25 Dec 2019)Before Git 2.27 (Q2 2020), allowing the user to split a patch hunk while "
git stash -p
" does not work well; a band-aid has been added to make this (partially) work better.See commit 7723436, commit 121c0d4 (08 Apr 2020) by Johannes Schindelin (
dscho
).(Merged by Junio C Hamano --
gitster
-- in commit e81ecff, 28 Apr 2020)Git 2.29 (Q4 2020) brings a leakfix to
git add -p
(used bystash -p
)See commit 324efcf (07 Sep 2020) by Phillip Wood (
phillipwood
).(Merged by Junio C Hamano --
gitster
-- in commit 3ad8d3e, 18 Sep 2020)在
git stash -p
以同样的方式失败后,我很幸运地使用了这个解决方法(git 2.0.2):git add -p
,拆分完全相同的内容帅哥,但答案相反(“y”到add
“保留”更改,“n”到stash
保留更改。)git stash -k
保留索引并存储其他所有内容git重置
以继续处理我的文件我不确定为什么
git add -p
没有以与git add -p相同的方式失败code>git stash -p
做到了。我想是因为添加与索引一起工作而不是创建补丁文件?After just having a
git stash -p
fail in this same way, I had luck with this workaround (git 2.0.2):git add -p
, splitting the exact same hunks but with inverse answers ("y" toadd
"keeps" changes, "n" tostash
keeps changes.)git stash -k
to keep the index and stash everything elsegit reset
to continue working on my filesI'm not sure why
git add -p
didn't fail in the same way thatgit stash -p
did. I guess because adding works with the index rather than creating a patch file?不幸的是,即使在 Git 2.17 中,目前接受的答案仍然可能失败。
如果像我一样,您花费了大量精力来构建完美的存储,并且不想放弃这些努力,那么仍然可以通过以下方式大部分获得您想要的东西:
git stash show -p | patch -p1 -R
这会失败并被拒绝,但很有可能大多数帅哥都会正确应用,并且至少可以节省您再次检查所有文件的时间。
The accepted answer at the moment can still unfortunately fail, even in Git 2.17.
If, like me, you spent a lot of effort constructing the perfect stash and don't want to throw that effort away, it is still possible to mostly get what you want with:
git stash show -p | patch -p1 -R
This will fail with rejects, but odds are good most of the hunks will apply correctly and at least save you the time of reviewing all the files again.