不丢弃本地更改的情况下切换Git分支

344

好的,假设有一天我们进行了大量修改,当我们想要将其提交时,我们发现我们正在错误的分支上工作。

如何强制Git切换分支而不丢弃本地更改

我可能会在等待回复的同时以一种天真的方式进行操作,但如果有正确的步骤,我想知道,因为我不得不承认这种情况以前发生过...

  • 备份更改后的仓库
  • git reset --hard
  • git checkout right-branch
  • 还原更改
  • git commit -m "changes"

4
git stash 是 Git 工具中用于保存当前工作进度的命令。当你需要切换分支但是当前工作还没有完成,又不想提交未完成的工作时,可以使用 git stash 命令将工作区和暂存区的修改保存起来,以便稍后恢复。你可以在任何时间通过 git stash apply 命令重新应用保存的工作进度,并继续进行原来的工作。 - zerkms
6个回答

547

根据您当前所在的分支和想要获取的分支,有许多不同的方法。

让我们来看一个经典错误:

$ git checkout master
... pause for coffee, etc ...
... return, edit a bunch of stuff, then: oops, wanted to be on develop

现在您希望这些更改应用到develop分支,但是它们还没有被提交到master分支。

  1. 如果您还没有develop分支,那么此方法很简单:

    $ git checkout -b develop
    

    这将从当前位置创建一个新的develop分支。现在您可以提交,新内容都在develop上。

  2. 您确实有一个develop。请尝试切换而无需进行任何操作:

  3. $ git checkout develop
    

    这要么成功,要么报错。如果成功了,太好了!只需提交。如果没有(error: Your local changes to the following files would be overwritten ...),你仍然有很多选择。

    最简单的方法可能是使用git stash(就像其他已经在我之前点击了post的回答者们所说的一样)。运行git stash savegit stash push1 或者直接使用git stash,它是save/push的缩写:

    $ git stash
    

    使用一种奇怪的非分支方法,这将提交您的代码(是的,它确实会进行一些提交)。它所做的提交不在任何分支上,但现在安全地存储在仓库中,因此您现在可以切换分支,然后"应用"贮藏:

    $ git checkout develop
    Switched to branch 'develop'
    $ git stash apply
    
    如果一切顺利,且您喜欢结果,那么您应该使用git stash drop命令来删除对不同于分支的奇怪提交的引用。(它们仍然存在于存储库中,并且在紧急情况下有时可以检索到它们,但对于大多数情况而言,您应该认为它们已经被删除了。)

    apply 步骤将合并暂存的更改,使用 Git 强大的底层合并机制,这与您执行分支合并时使用的方式相同。 这意味着,如果您错误地在一个分支上工作,而该分支与您想要工作的分支有很大不同,那么您可能会遇到“合并冲突”。因此,在假定未发现任何合并冲突的情况下,建议您在继续之前仔细检查结果

    许多人使用 git stash pop,这是git stash apply && git stash drop的简写形式。 虽然这样做没什么问题,但如果应用程序的结果很混乱,并且您决定不想继续沿着这条路走,就不能轻松地获取暂存内容。这就是为什么我建议分别使用apply命令,检查结果,只有在满意时再使用drop命令。(当然,这样会引入另一个点,您可能会在此期间休息一下,忘记自己正在做什么,回来后执行错误的操作,因此它并不是完美的解决方案。)

    1git stash save中,“save”是创建新暂存内容的旧动词。 Git 2.13 版本引入了新动词,以使事情更加一致,并向创建命令添加更多选项。 Git 2.16 正式弃用了旧动词(尽管在我编辑此文本时,最新版本为 Git 2.23,旧动词仍然可以使用)。

4
如果我想在不提交当前分支的情况下切换到另一个分支(例如,更改未完成),然后稍后再切换回来继续进行,应该怎么办? - dragonfly02
1
@nanocv:请参见https://dev59.com/OmEh5IYBdhLWcg3wwly8。 - torek
当我按以上步骤切换时,所有本地更改都会丢失。我在<a>分支中进行更改,并希望移动到<b>分支并将所有更改推送到其中。当我执行git stash并移动到其他分支时,它会拉取<b>分支的所有文件,而我的本地更改会丢失。 - Cycl0n3
@MukulMunjal:git stash的意思是先进行一些提交,然后将我的更改拿走,因为它们已经安全地保存在存储提交中。所以当你把它们藏起来后,它们当然就消失了:这就是藏起来的目的,既可以摆脱它们,同时也可以保存它们。你必须随后使用git stash apply取消隐藏它们。在这两个步骤之间,您可以随意切换分支。 - torek
1
@Brian:git stash只是进行提交而已。Git的几个版本中已经出现了一些引入错误的git stash,因此我现在建议 尽可能避免 使用git stash - torek
显示剩余11条评论

88

使用 git stash

git stash

它将更改推到堆栈中。当您想要将它们拉回时,请使用

git stash apply
你甚至可以单独提取项目。 完全清除暂存区的方法:
git stash drop

19
最后一个命令应该是 git stash dropgit stash clear会清除整个贮藏堆栈,包括可能与这组命令无关的贮藏。请注意不要改变原文的意思。 - Leland

47
你可以使用以下命令:
  1. git stash 保存你的工作
  2. git checkout <your-branch>
  3. git stash apply 或者 git stash pop 加载你最后保存的工作

当你想要在另一个分支上进行操作时,Git stash非常有用,它可以暂时保存未完成或混乱的工作。

git -stash 文档


1
这是问题最优雅的解决方案 - 不仅在隐含逻辑上...而且它也非常容易记住! - Ahi Tuna

28
  • git stash 命令可以保存你未提交的更改
  • git stash list 命令可以列出你保存的未提交更改的备份列表
  • git stash apply stash@{x} 命令中的x代表你所做的备份编号(可以是0,1,2...等等)

12
你可以使用--merge/-m选项来进行 git checkoutgit checkout -m <另一个分支> -m --merge 当切换分支时,如果你有一个或多个文件在当前分支和要切换的分支之间存在差异并且这些文件已经被修改了,该命令会拒绝切换分支以保护你的修改内容。但是,使用此选项时,会在当前分支、工作树内容和新分支之间进行三方合并,然后你将进入新分支。
来源:https://git-scm.com/docs/git-checkout

首先尝试使用简单的 git checkout thatbranch 命令,如果完全安全且您所做的更改未涉及到被检出更新的文件,则此命令可行。 - jthill
1
@sergey.n 我认为你的答案是正确的。封存并不总是有效的,它在子模块、暂存和如果你在没有提交的分支上时会出现问题。然而,你可以将更改合并到一个新的分支中。 - Jeff Hykin
针对初学者阅读评论部分:为了避免使用git checkout意外进入分离的HEAD状态,最好使用以下概要: $ git switch -c <another-branch> --merge - projektorius96
@Amun,你现在使用的是哪个版本的bash、dash或相关shell来运行git?似乎你选择的shell不认识即不存在这样的命令。据我所知,自Git 2.23或更高版本以来,git switch才开始生效。如果你的shell版本低于此版本,那么你可能会遇到错误。请告诉我。 - projektorius96
1
@projektorius96 我感觉自己很蠢,但我的服务器git版本太旧了。抱歉并感谢您的回答。随意删除,因为这可能对其他人没有帮助。 - Amund

7
你可以选择以下两种方法之一:
  • 使用git stash将你的更改存储起来,或者

  • 创建另一个分支并在那里提交你的更改,然后将该分支合并到你的工作目录中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接