为什么`git stash -p`有时会失败?

时间:2011-02-18 22:46:52

标签: git git-stash

我♥git stash -p。但有时候,在满意的yns会话之后,我会明白这一点:

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

为什么?

5 个答案:

答案 0 :(得分:27)

任何时候我试图将一个大块分成太近的小伙伴(变化之间少于3行)。简短的解释是补丁中包含与您的本地更改冲突的上下文行。下面有更完整的解释。


假设我有一个带有这些未提交更改的git repo:

--- a/pangram
+++ b/pangram
@@ -1,8 +1,8 @@
 The
-quick
+relatively quick
 brown
 fox
-jumps
+walks
 over
 the
 lazy

如果我收藏第一个更改,我会:

--- a/pangram
+++ b/pangram
@@ -1,5 +1,5 @@
 The
-quick
+relatively quick
 brown
 fox
 jumps

git stash命令实际上确实成功保存了补丁(检查git stash list),但是然后git反向使用该补丁来从我的工作目录中删除隐藏的更改。大块头之后的上下文有“跳跃”,这与我工作目录中的“行走”不匹配。所以git拯救了

error: patch failed: pangram:1
error: pangram: patch does not apply
Cannot remove worktree changes

并留下我工作目录中的所有变化,并且藏匿变得毫无价值。


我认为这是git的大块分裂支持中的一个错误。如果它知道它将这些变化分得太近,它可以从补丁中删除几行上下文,或者使补丁变得简单,以获得修改后的上下文行而不是原始行。或者,如果将这种情况分开,这种关闭是正式不受支持的,它实际上应该拒绝分离那些关闭的人。

答案 1 :(得分:6)

在以同样的方式发生git stash -p失败之后,我对此解决方法很有好处(git 2.0.2):

  • git add -p,将完全相同的帅哥分开,但使用反向答案(“y”到add“保持”变化,“n”到stash保持变化。)
  • git stash -k保留索引并隐藏其他所有内容
  • git reset继续处理我的文件

我不确定为什么git add -p没有像git stash -p那样失败。我想因为添加索引而不是创建补丁文件?

答案 2 :(得分:6)

使用Git 2.17(2018年第二季度),

git stash -p应该会失败 在此之前,“git add -p”(与git stash共享逻辑)在将结果传递给基础“git apply”之前,在合并拆分补丁方面一直很懒惰,导致了角落案例错误;在收紧大块选择之后准备要应用的补丁的逻辑。

请参阅commit 3a8522fcommit b3e0fcfcommit 2b8ea7f(2018年3月5日),commit fecc6f3commit 23fea4ccommit 902f414(2018年3月1日),和commit 11489a6commit e4d671ccommit 492e60c(2018年2月19日)Phillip Wood (phillipwood)(由Junio C Hamano -- gitster --合并于commit 436d18f,2018年3月14日)

  

add -p:在跳过一个时调整后续帅哥的偏移量

(添加,但同样可以应用于藏匿)

  

commit 8cbd431(“git-add--interactive:”替换hunk   使用apply --recount“,2008-7-2,Git v1.6.0-rc0进行重新计数)如果跳过一个大块,那么我们依靠上下文线来应用右边的后续   地点。

     

虽然大多数时候这种情况有效,但是帅哥可能会这样做   最终被应用在错误的地方。

     

要解决此问题,请调整偏移量   随后的帅哥纠正任何数量的变化   由于跳过的大块而导致的插入或删除。偏移量的变化   由于编辑的帅哥有插入或删除的数量   这里忽略了更改,它将在下次提交时修复。

您可以看到some tests here

Git 2.19改进了git add -p:当用户在“git add -p”中编辑补丁并且用户的编辑器被设置为不加区别地删除尾随空格时,补丁中未更改的空行将变为完全为空(而不是带有唯一SP的线) 在Git 2.17时间框架中引入的代码无法解析这样的补丁,但现在它学会了注意这种情况并应对它。

commit f4d35a6Phillip Wood (phillipwood)(2018年6月11日) (由Junio C Hamano -- gitster --合并于commit 5eb8da8,2018年6月28日)

  

add -p:修复已编辑补丁中的空上下文行计数

     commit 2b8ea7f中引入了

recount_edited_hunk()(“add -p:   计算修补补丁的偏移增量“,2018-03-05,Git v2.17.0”要求所有上下文行以空格开头,不计算空行。
  这是为了避免任何重新计数问题,如果用户在编辑补丁时在末尾引入了空行。

     

然而,这引入了对“git add -p”的回归,因为编辑器在编辑补丁时从空上下文行中剥离尾随空格似乎很常见,从而引入应该是空行的空行   计数。
  'git apply'知道如何处理这些空行,POSIX声明空上下文行是否有空格是实现定义的(参见diff command)。

     

通过计算仅包含换行符的行来修复回归   以及以空格开头的行作为上下文行并添加测试   以防止未来的回归。

答案 3 :(得分:4)

即使在Git 2.17中,目前接受的答案仍然可能失败。

如果像我一样,你花费了很多精力来构建完美的藏匿点并且不想抛弃那些努力,那么仍然可以大部分得到你想要的东西:

git stash show -p | patch -p1 -R

这会因拒绝而失败,但赔率很高,大多数帅哥都会正确应用,至少可以节省你再次审阅所有文件的时间。

答案 4 :(得分:-2)

应用状态可能会因冲突而失败;在这种情况下,它不会从隐藏列表中删除。您需要手动解决冲突并随后手动调用git stash drop