如何解决git stash冲突而无需提交?


494

正如这个问题中问的那样,我还想知道如何解决冲突git stash pop而不向提交中添加所有修改(就像没有冲突的“ git stash pop”一样)。

我目前的方法非常不明智,因为我是这样进行的:

git stash pop -> CONFLICT
git stash drop
[resolve conflict]
[add conflict files]
git reset HEAD <all files that are in commit-mode>

[更新]再现它的方法:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27:在示例中添加了一个名为“ third”的新文件,以显示类似scy的解决方案之类的解决方法仅适用于空HEAD,但不能解决HEAD与内容不相同的最初问题对于git stash pop没有冲突。


因此,您git add将已解决的冲突文件有效地存储在索引中,并且不想在我们的索引中包含它们?
罗曼(Romain)

恩,那就对了。我只想要git stash pop没有冲突发生时的行为(但需要通知哪些文件需要合并)。
斯文

2
似乎答案在这里:stackoverflow.com/questions/3945826/git-stash-questions。在选择的答案中,关于第4条评论,Adam解释了git为什么这样做。
Patrick

@Patrick谢谢您提供的信息-似乎将没有解决方案,因为它是“按设计的”
Sven 2012年

Answers:


506

不要遵循其他答案

好吧,您可以关注他们:)。但是我不认为先提交然后重置分支以删除该提交,其他答案中建议的类似变通办法不是解决此问题的干净方法。

清洁溶液

以下解决方案对我来说似乎更干净,Git本身建议使用以下解决方案-尝试git status在存储库中发生冲突:

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

因此,让我们按照Git的建议进行操作(不执行任何无用的提交):

  1. 手动(或使用某些合并工具,请参见下文)解决冲突。
  2. git reset马克冲突(S)为解决和unstage的变化。您可以不带任何参数地执行它,Git将从索引中删除所有内容。您不必先执行git add
  3. 最后,使用删除存储git stash drop,因为Git在冲突时不会这样做。

转换为命令行:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

默认行为的说明

有两种方法将冲突标记为已解决:git addgit reset。虽然git reset将冲突标记为已解决并从索引中删除文件git add,但也将冲突标记为已解决但将文件保留在索引中。

解决冲突后将文件添加到索引是有意的。这样,您就可以区分与先前存储区所做的更改以及在解决冲突后所做的更改。如果您不喜欢它,可以随时使用git reset从索引中删除所有内容。

合并工具

我强烈建议使用任何一种三向合并工具来解决冲突,例如KDiff3Meld等,而不要手动进行。通常,它本身可以自动解决所有或大部分冲突。这是巨大的节省时间!


32
@kamalpal似乎在git stash pop冲突失败时需要。
Emile Bergeron'3

21
@kamalpal是的,Git甚至会通知您在发生冲突的情况下没有隐藏存储。问题是关于这种情况的,因此除非您不想保留该存储,否则您确实需要执行git stash drop
David FerenczyRogožan16年

@DavidFerenczyRogožanGit根本没有通知我它没有删除隐藏条目。版本2.17.1在这里。
罗伯·西默

298

假设您有这种情况,其中存储您的更改以便从原点撤出。可能是因为您的本地更改仅debug: true在某些设置文件中。现在您拉动,有人在那里引入了新设置,从而产生了冲突。

git status 说:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

好的。我决定接受Git的建议:解决了冲突并做出了以下承诺:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

现在我的工作副本处于我想要的状态,但是我创建了一个我不想拥有的提交。如何在不修改工作副本的情况下摆脱该提交?等等,有一个流行的命令!

git reset HEAD^

我的工作副本尚未更改,但是WIP提交已消失。那正是我想要的!(请注意,我不在--soft这里使用,因为如果您的存储中有自动合并的文件,它们将被自动暂存,因此最终您将不得不在之后再次暂存这些文件reset。)

但是还有一件事:手册页git stash pop提醒我们:“应用状态可能会因冲突而失败;在这种情况下,不会从存储列表中删除该状态。您需要git stash drop手动解决冲突,然后手动进行调用。” 这就是我们现在要做的:

git stash drop

并做了。


34
故意要执行commit reset HEAD ^ ...有很多继承丑陋的事情,这些事情只会影响工作树。

6
为什么不只是解决冲突,然后git add <resolved conflict files>其次是git reset HEAD
BoltzmannBrain 2015年

感谢您的建议,但这不能解决最初的问题,即与git stash pop没有冲突的行为不同。只需在冲突之前将另一个文件添加到HEAD即可,然后git stash popgit commit -a -m WIP还可以将新文件添加到提交中。但是没有冲突,只是新文件将保留在HEAD中,而不是git stash pop文件。

7
我认为没有必要先提交然后撤消提交。只需从Dawid Ferenczy的答案中重置就可以做到这一点
vladkras '16

3
对于Windows用户,^用作特殊行的延续,会让您坐在“更多”页面上。提示而不是执行命令。而是使用:git reset --soft HEAD~1。看看我如何删除未推送的git-commits吗?
mrfelis '17

87

无需添加git reset HEAD file为解决冲突而进行的更改,而是可以使用冲突来解决冲突而无需进行任何更改。

但是,您可能必须运行两次此命令。一次将冲突标记为已解决,一次撤消由冲突解决例程执行的更改。

尽管目前没有复位模式,但应该有一种可以同时完成这两项操作的复位模式。


2
重置模式是我要搜索的一种-其他解决方法与我描述的一样,并且不适用于5个以上的文件。
Sven

25
然后使用“ git stash drop”完成“ git stash pop”。
大卫·刘

2
尽管该问题并未明确要求这样做,但更新答案以包括“ git stash drop”可能会很有用,因为在发生冲突的情况下不会自动删除存储。
Abhishek Pathak 2015年

29
git checkout stash -- .

为我工作。

:这可能是危险的,因为它不尝试从藏匿的修改合并到你的工作拷贝,但覆盖与藏文件,而不是它。因此,您可能会丢失未提交的更改。


当“ git pull --autostash”引入不需要的合并提交和git checkout stash-时,这很有帮助。无条件覆盖
隐藏的

11
git add .
git reset

git add . 将暂存所有文件,告诉git您已解决冲突

git reset 将取消转储所有已转储的文件而不创建提交


这实际上不是一个坏答案,这很像git add -u那时git reset
ebob

4

看来这可能是您要寻找的答案,我还没有亲自尝试过,但似乎可以解决问题。使用此命令,GIT将尝试像以前一样应用更改,而不尝试添加所有更改以进行提交。

git stash apply --index

这是完整的解释:

http://git-scm.com/book/en/Git-Tools-Stashing


感谢您提供此提示,但是当我已经git stash pop做完git stash apply --index时这将无济于事-还是有办法还原并在发现git stash pop冲突时执行该操作?
2012年

我添加了一个有关如何生成此文件的示例-假设您正在编辑10个以上的文件,因此您不知道在存储区之外修改了哪些文件。
2012年

3
如果你看看这个帖子底部的位置,它说,如果你运行git stash pop,并与冲突结束了,藏匿不会被删除......这样你就可以运行git reset --hard撤消弹出,然后尝试我所建议的解决方案。
Marco Ponti'3

只是尝试了一下,当文件处于冲突状态后它不起作用。即使您手动解决冲突。
Sam3k 2014年

2

git stash branch将起作用,它将为您创建一个新分支,签出您存放工作时所处的提交,在此处重新应用您的工作,如果成功应用,则删除存储。检查一下


2

我发现最快的方法是解决冲突,然后执行git add -u,然后执行git reset HEAD,甚至不涉及提交。


1

根据git stash的问题,解决冲突后,git add <file>正确的做法是。

读完此评论后,我了解到更改是自动添加到索引中的(通过设计)。这就是为什么要git add <file>完成冲突解决过程的原因。


-1

它不是最好的方法,但是可以起作用:

$ git stash apply
$ >> resolve your conflict <<
$ >> do what you want to do with your code <<
$ git checkout HEAD -- file/path/to/your/file

这个答案对我来说似乎是完全错误的,因为它将放弃对的所有更改file/path/to/your/file,这不是OP要求的,AFAIU
oromoiluig
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.