git stash blunder:git stash pop并最终导致合并冲突


200

我做了git stash pop并最终导致合并冲突。我从文件系统中删除了文件,并进行了git checkout如下所示的操作,但它认为这些文件仍未合并。然后,我尝试替换文件并git checkout再次执行相同的结果。我事件尝试用-f标志强制它。任何帮助,将不胜感激!

chirag-patels-macbook-pro:haloror patelc75$ git status
app/views/layouts/_choose_patient.html.erb: needs merge
app/views/layouts/_links.html.erb: needs merge
# On branch prod-temp
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   db/schema.rb
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       unmerged:   app/views/layouts/_choose_patient.html.erb
#       unmerged:   app/views/layouts/_links.html.erb

chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb
error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb
warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged

注:恢复状态之前git stash apply/pop应该是使用Git 2.5(2015年第二季度)更容易,因为工作树现在需要清洁:看到我的回答如下
VonC

Answers:


219

参见man git merge如何解决冲突):

看到冲突后,您可以做两件事:

  • 决定不合并。您需要执行的唯一清除操作是将索引文件重置为HEAD commit以反转2,并清除2和3对工作树所做的更改。git-reset --hard可以用于此目的。

  • 解决冲突。Git将在工作树中标记冲突。将文件编辑为shape并git将它们添加到索引中。使用git commit来完成交易。

TRUE MERGE下(查看2.和3.指的是什么):

如果不清楚如何协调更改,则会发生以下情况:

  1. HEAD指针保持不变。

  2. MERGE_HEAD ref设置为指向另一个分支头。

  3. 干净合并的路径会在索引文件和工作树中同时更新。

  4. ...

因此:git reset --hard如果您想从工作树中删除隐藏更改,或者git reset只想清理索引并将冲突留在工作树中以手工合并,请使用。

man git stashOPTIONS,pop)下,您还可以阅读以下内容:

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


9
实际上,即使在删除存储库之后,仍然有可能(尽管更加困难)再次检索它,因为更改集仍存在于存储库中。stackoverflow.com/search?q=git+recover+dropped+stash
Phils

3
@nalply:是好是坏?欢迎您改进我的答案,如果您不了解它的话……
tanascius 2011年

1
我认为源代码修订是一个复杂的问题领域。很容易感到困惑。我仍然认为您的回答很好,因为它再次确认了我的做法。
2011年

1
这不仅使我认识到并没有像我想象的那样移除储藏物,而且对我很有帮助,这也解释了为什么即使我确定我没有忘记从储藏物中取回东西,我的储藏物仍在增长。
Thor84no 2015年

11
“应用状态可能会因冲突而失败;在这种情况下,不会将其从存储列表中删除。” 我认为,这是该帖子中最重要的部分。考虑编辑您的答案,以大而友好的字母加上“ 不要恐慌 ”一词。(不过+1)。谢谢。
Patrick M

42

我也发生了类似的事情。我还不想暂存文件,所以我添加了它们,git add然后添加了它们git reset。基本上,这只是添加然后取消暂存我的更改,但清除了未合并的路径。


4
这似乎比使用更好,reset --hard因为它不会覆盖您的文件(具有合并问题的文件除外)。谢谢!
sinelaw

我现在还不想暂存文件,所以我添加了它们 -暂不将add内容从工作树暂存到索引吗?我认为我不明白为什么您的回答会从说明中起作用。
德鲁·诺阿克斯

2
git add确实对它们进行了登台,但是git reset,我在之后立即取消对它们的登台。本质上,它清除了未合并的路径,并通过伪造git使我回到正常的工作树中。
亚伦

3
如果您要这样做,git add则不需要git reset。将git reset有效地“撤销”的git addgit reset--mixed<-默认)有效地不会接触工作目录,因此,工作目录中的内容,合并冲突以及所有内容都将被单独保留。索引(以及技术上是分支头)将被重置(没有引用,它们将被重置回HEAD,这可能意味着分支头没有任何变化,并有效地撤消git add了对索引所做的任何操作,并清除了未合并的路径状态) 。
bambams 2014年

3
序列编辑/决心git resetgit stash drop运行良好。它git stash pop会做没有冲突的事情。似乎确实git add不需要。尽管它可能很有用,但是您有许多冲突文件。在解决每个问题时,可以添加它们并git status跟踪它们。
无声的噪音

13

如果像我一样,通常想要用隐藏文件覆盖工作目录的内容,而您仍然遇到冲突,那么您要使用的是git checkout --theirs -- .从根目录解决冲突。

此后,您可以git reset将所有更改从索引移到工作目录,因为显然在发生冲突的情况下,对非冲突文件的更改将保留在索引中。

您可能还希望git stash drop [<stash name>]随后运行以摆脱隐藏,因为git stash pop在发生冲突的情况下不会将其删除。


2

注意 Git 2.5(2015年第二季度) 未来的Git可能会尝试使这种情况成为不可能。

提交ed178ef杰夫·金peff),4月22日2015年
(由合并JUNIOÇ滨野 - gitster-在提交05c3967,19 2015年5月)

注意:这已恢复。见下文

stash:要求一个干净的索引才能应用/弹出

问题

如果您已在索引中暂存内容并运行“ stash apply/pop”,则我们可能会发生冲突,并在索引中添加新条目。
那时很难恢复到原始状态,因为“ git reset --keep”之类的工具会炸掉所有上演的东西

换一种说法:

git stash pop/apply”忘记确保不仅工作树是干净的,而且索引也是干净的。
后者很重要,因为存储应用程序可能会发生冲突,并且索引将用于解决冲突。

我们可以通过在阶段性更改时拒绝应用来使此操作更安全。

这意味着,如果之前由于在修改后的文件上添加了存储(添加但未提交)而进行了合并,则它们将不再是任何合并,因为存储的应用/弹出将立即停止,并显示以下内容:

Cannot apply stash: Your index contains uncommitted changes.

强制您提交更改意味着在合并的情况下,您可以使用轻松恢复初始状态(before git stash apply/popgit reset --hard


犯1937610(2015年6月15日),并提交ed178ef(2015年4月22日),由杰夫·王(peff
(通过合并JUNIOÇ滨野- gitster-提交bfb539b 6月24日2015)

该提交是为了提高应用存储的安全性的尝试,因为应用程序过程可能会创建冲突的索引条目,此后很难恢复原始索引状态。

不幸的是,这伤害了一些围绕“ git stash -k”的常见工作流程,例如:

git add -p       ;# (1) stage set of proposed changes
git stash -k     ;# (2) get rid of everything else
make test        ;# (3) make sure proposal is reasonable
git stash apply  ;# (4) restore original working tree

如果您在步骤(3)和(4)之间进行“ git commit”,则此方法就可以了。但是,如果这些步骤是预提交挂钩的一部分,则您没有机会(无论测试通过还是失败,都必须恢复原始状态)。

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.