Git隐藏:“无法应用于肮脏的工作树,请进行更改”


133

我正在尝试应用先前藏git stash pop有的更改并获得消息:

Cannot apply to a dirty working tree, please stage your changes

关于如何处理的任何建议?

Answers:


196

当我必须将隐藏的更改应用于脏的工作副本(例如,从存储中弹出多个更改集)时,可以使用以下命令:

$ git stash show -p | git apply -3 && git stash drop

基本上是

  1. 创建一个补丁
  2. 管道到apply命令
  3. 如果有任何冲突,则需要通过三向合并解决
  4. 如果成功应用(或合并),它将丢弃刚刚应用的存储项...

我想知道为什么没有-f(force)选项的git stash pop行为应该完全像上面的单行代码。

同时,您可能希望将此单行添加为git别名:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

感谢@SamHasler指出了-3允许通过三向合并直接解决冲突的参数。


git stash show -p | git apply不是不同git stash apply
Factor Mystic

1
git stash apply如果您的工作副本很脏,Jo Factor 将不会应用隐藏的更改。因此,您可以看到git stash show -p | git apply某种形式的强制隐藏。
muhqu 2011年

1
无济于事,但有帮助:git reset HEAD,然后取消隐藏更改。
罗杰·阿里恩

4
我收到其中一个文件的“错误:补丁失败...补丁不适用”。我希望它给合并带来了冲突。
Aleksandr Dubinsky 2014年

1
该解决方案对我不起作用,error: <file> does not match index对于每个修改的文件均失败。但是,另一种解决方案有效。
silvenon

57

我这样做:

git add -A
git stash apply

然后(可选):

git reset

2
+1!这比涉及生成补丁或修改提交的其他解决方案要简单,并且可以确保本地更改与应用的存储更改安全隔离,直到您确定更改已正确合并为止。
peterflynn

我收到错误消息“ ...已经存在,没有签出...无法从存储中还原未跟踪的文件”
Aleksandr Dubinsky 2014年

2
我使用了git add -u-A除了不添加未跟踪的文件外,这就像。
布拉德·库皮

9

您可以通过将所需的存储导出为补丁文件并手动应用它,而不必存储当前更改,而无需存储当前更改。

例如,假设您要将stash @ {0}应用于脏树:

  1. 将stash @ {0}导出为补丁:

    git stash show -p stash @ {0}> Stash0.patch

  2. 手动应用更改:

    git apply Stash0.patch

如果第二步失败,则必须编辑Stash0.patch文件以修复任何错误,然后再次尝试git apply。


对于以下情况,这是实用且可行的:我在目录上进行了重构(将其删除,并使用其名称创建了符号链接)。Git无法告诉我我的工作副本更改是什么。
yclian

1
这很棒。即使我很确定我的工作树很干净,我也无法应用存储。
Shiki 2010年

是的,我必须删除有关二进制文件的行。
多里安(Dorian)2012年

8

可以使用git reset清理工作目录,提交更改,或者如果要存储当前更改,请尝试:

$ git stash保存“当前更改描述”
$ git stash pop stash @ {1}

这将存储当前更改,然后从存储堆栈中弹出第二个存储。


5
但是这个家伙想要应用两个隐藏!
Elazar Leibovich

@Elazar您正在阅读问题。OP仅希望应用先前的存储。如果您正确保留了当前更改,则可以重复执行该解决方案:弹出,提交,重复。
William Pursell 2011年

我认为他希望他们两个都不做。但是话又说回来,他可以将它们提交两次,并将它们压缩为一次提交。
Elazar Leibovich

我收到错误消息“ ...已经存在,没有签出...无法从存储中还原未跟踪的文件”
Aleksandr Dubinsky 2014年

6

Mathias的解决方案绝对是最接近git stash pop --force的解决方案(实际上,请教Git开发人员,让我们已经拥有此选项!)

但是,如果您只想使用git命令做同样的事情,则可以:

  1. git commit -a -m“修复”
  2. git stash pop
  3. git commit -a --amend
  4. git reset HEAD〜

换句话说,提交(我们将永远不会推送)您当前的更改。现在您的工作区已经干净了,弹出存储。现在,提交隐藏更改,作为对先前提交的修订。完成后,您现在将两组更改组合在一个提交中(“ Fixme”);只需将您的结帐重置为(“软NOT-硬,因此实际上不会丢失”),然后将结帐设置为“该提交之前一个”,现在您已经完成了两组更改,完全没有提交。

**编辑* *

我只是意识到实际上更容易。您可以完全跳过步骤3,因此...

  1. git commit -a -m“修复”
  2. git stash pop
  3. git reset HEAD〜

(提交当前更改,弹出隐藏的更改,重置第一个提交以使两组更改合并到未提交状态。)


4

如果您像我今天那样处于这种情况,那么这些答案都不会真正起作用。不管git reset --hard我做了多少,它都无济于事。我的回答(绝对不是官方的):

  1. 找出隐藏的哈希使用 git reflog --all
  2. 将该哈希与您感兴趣的分支合并

1
非常感谢Yar。Git刚在我的本地存储库中表现异常,令我感到沮丧,这与您描述的问题相同。
yclian 2011年

4

我还发现Mathias Leppich的解决方案效果很好,因此我在全局.gitconfig中为其添加了别名

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

现在我可以输入

git apply-stash-to-dirty-working-tree

对我来说很棒。

(对于这个长别名,您的里程可能会有所不同。但是,在进行bash补全时,我喜欢一定程度的冗长。)


3

通过执行暂存所做的git add任何更改,您可以将隐藏项应用于“脏”树,从而清理树。然后,您可以git stash pop并应用隐藏的更改,没问题。


2

您有已修改但尚未提交的文件。要么:

git reset --hard HEAD (to bring everything back to HEAD)

或者,如果您要保存更改:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop

1
@MikeCooper-我认为他的意思是在提交之前添加您想要添加的任何内容。
sscirrus '02

0

我有同样的问题,但是git更改了零个文件。原来我有一个index.lock文件在附近。删除它可以解决问题。


0

我无法使其中的大多数工作。由于某种原因,它总是认为我对文件进行了本地更改。我无法应用存储,补丁无法应用,checkout并且reset --hard失败。最终有效的方法是将隐藏项保存为git stash branch tempbranchname,然后进行常规的分支合并:git checkout mastergit merge tempbranchname。从http://git-scm.com/book/en/Git-Tools-Stashing

如果您想要一种更简便的方法来再次测试隐匿的更改,可以运行git stash分支,该分支为您创建一个新分支,签出隐匿您的工作时所做的提交,在此处重新应用您的工作,然后删除存放成功

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.