Git stash: “不能应用于脏的工作树,请进行更改”

我正在尝试应用之前藏在 git stash pop中的更改,并得到以下信息:

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

有什么建议吗?

54913 次浏览

要么用 git 重置清理工作目录,提交更改,要么,如果你想隐藏当前更改,试试:

$ git stash save "description of current changes"
$ git stash pop stash@{1}

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

您的文件已被修改,但尚未提交:

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

您可以这样做,而不必隐藏您当前的更改,方法是将所需的隐藏文件作为补丁文件导出并手动应用它。

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

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

    git stash show -p stash@{0} > Stash0.patch
    
  2. 手动应用更改:

    git apply Stash0.patch
    

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

当我必须对一个脏的工作副本应用隐藏的变更时,例如从隐藏的变更集中弹出多个变更集,我使用以下方法:

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

差不多吧

  1. 创建一个补丁
  2. 将其传送到 application 命令
  3. 如果有任何冲突,他们将需要通过3方合并来解决
  4. 如果应用(或合并)成功,它删除刚刚应用的隐藏项目..。

我想知道为什么没有 -f(力)选项的 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参数,它允许通过3路合并直接解决冲突。

如果你发现自己像我今天这样处于这种情况,这些答案实际上都不起作用。不管我做了多少次 git reset --hard都没有结果。我的回答(无论如何都不是官方的)是:

  1. 使用 git reflog --all计算出存储的散列
  2. 将这个散列与您感兴趣的分支合并

我还发现 Mathias Leppich 的解决方案工作得很好,所以我为它添加了一个别名到我的 global. 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 完成时,我喜欢冗长。)

我也有同样的问题,但是 git 没有任何修改过的文件。发现我有一个 index.lock 文件。删除它解决了问题。

您可以通过执行 git add来阶段您所做的任何更改,从而清理“脏”树。然后您可以 git stash pop和应用隐藏的更改,没有问题。

Mathias 的解决方案无疑是最接近 git stash pop --force的(真的,来吧 Git 开发人员,让我们已经有了这个选项!)

但是,如果只想使用 Git 命令执行相同的操作,则可以:

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git commit -a --amend
  4. git reset HEAD~

换句话说,对当前的更改进行提交(我们永远不会推送)。既然您的工作空间已经清理干净,那么打开您的存储空间。现在,提交隐藏更改作为对以前提交的修正。做完这些之后,你现在已经在一个提交(“ Fixme”)中将两组更改组合在一起了; 只需要 git reset(--soft NOT --hard,因此实际上没有丢失任何东西) ,你的签出到“ one before that commit”,现在你已经有了两组更改,完全未提交。

剪辑

我刚意识到这其实更简单你完全可以跳过第三步,所以..。

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git reset HEAD~

(提交当前更改,取消隐藏的更改,重置首次提交的更改,以使两组更改合并为未提交状态。)

我是这样做的:

git add -A
git stash apply

然后(可选) :

git reset

我无法让其中的大部分工作; 出于某种原因,它总是认为我对文件进行了本地更改。我不能应用一个隐藏,补丁不会适用,checkoutreset --hard失败。最后,我们使用 git stash branch tempbranchname将存储保存为一个分支,然后执行一个正常的分支合并: git checkout mastergit merge tempbranchname。 来自 http://git-scm.com/book/en/Git-Tools-Stashing:

如果您希望再次测试隐藏的更改,可以使用更简单的方法 运行 git 存储分支,它会为您创建一个新分支,结束 当你藏起你的作品,重新运用你的作品时,你所做的承诺 然后,如果成功应用,则放弃隐藏

这就是我对这个问题的看法,这个问题对我来说没有任何问题。

git stash show | patch -p1

当然,它部分地借助于 git命令系统之外的命令。