880

我的开发分支中有一些未提交的更改,我使用 隐藏了它们git stash,但是在这些隐藏的更改中有些更改非常重要。有没有办法恢复这些变化?

此外,从那以后,我对隐藏的代码文件进行了一些更改。

如果可能的话,我是否有机会将隐藏的更改检索到新分支?

4

6 回答 6

1509

简单问题的简单答案是git stash apply

只需检查您想要更改的分支,然后git stash apply. 然后使用git diff来查看结果。

在您完成所有更改之后(apply看起来不错,并且您确定不再需要存储)<em>然后使用git stash drop它来摆脱它。

我总是建议使用git stash apply而不是git stash pop. 不同之处在于,apply留下存储以便于重试apply或查看等。如果pop能够提取存储,它也会立即提取drop它,如果您随后意识到您想在其他地方提取它(在不同的分支中),或者 with --index,或者类似的,这并不容易。如果你apply可以选择什么时候去drop

无论如何,这一切都很次要,对于 Git 的新手来说,应该差不多。(你可以跳过所有其他的!)


如果您正在做更高级或更复杂的事情怎么办?

至少有三四种不同的“使用 git stash 的方法”。以上是“方式1”,“简单方式”:

  1. 你从一个干净的分支开始,正在进行一些更改,然后意识到你在错误的分支中进行了这些更改。您只想将现有的更改“移动”到另一个分支。

这是简单的情况,如上所述。运行git stash save(或plain git stash,同样的事情)。查看另一个分支并使用git stash apply. 这让 Git 使用 Git 相当强大的合并机制来合并您之前的更改。 仔细检查结果(用git diff),看看你是否喜欢它们,如果喜欢,使用git stash drop删除存储。你完成了!

  1. 您开始了一些更改并将它们隐藏起来。然后你切换到另一个分支并开始了更多的更改,忘记了你有隐藏的那些。

现在您想保留甚至移动这些更改,应用您的存储。

实际上,您可以git stash save再次git stash进行“堆栈”更改。如果你这样做,你有两个 stashes,一个刚刚调用stash- 但你也可以写stash@{0}- 一个拼写stash@{1}. 使用git stash list(随时)查看所有内容。最新的总是编号最低的。当 you 时git stash drop,它会丢弃最新的,以及stash@{1}移动到堆栈顶部的那个。如果你有,甚至更多,那个stash@{2}变成了stash@{1},依此类推。

您也可以apply使用drop特定的存储:git stash apply stash@{2},依此类推。删除特定的存储只会重新编号编号较高的存储。同样,没有数字的也是stash@{0}

如果你堆积了很多藏匿处,它会变得相当混乱(是我想要的藏匿处stash@{7}还是它stash@{4}?等等,我刚刚推了另一个,现在它们是 8 和 5?)。我个人更喜欢将这些更改转移到一个新分支,因为分支有名称,并且cleanup-attempt-in-December对我来说比stash@{12}. (该git stash命令需要一个可选的保存消息,这些可以提供帮助,但不知何故,我所有的存储都只是命名为WIP on branch。)

  1. git stash save -p(超高级)git addgit rm运行git stash save. 您在隐藏的索引/暂存区域中有一个版本,在工作树中有另一个(不同的)版本。你想保留这一切。所以现在你使用git stash apply --index, 有时会失败:

    Conflicts in index.  Try without --index.
    
  2. 您正在使用git stash save --keep-index以测试“将要提交的内容”。这个超出了这个答案的范围;请参阅此其他 StackOverflow 答案

对于复杂的情况,我建议首先从“干净”的工作树开始,提交您现在拥有的任何更改(如果您愿意,可以在新分支上)。这样,您正在应用它们的“某处”就没有其他内容了,您将只是尝试隐藏的更改:

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

现在你处于一个“干净”的起点。或者它可能更像这样:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create a new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

要记住的主要事情是“stash”一个提交,它只是一个稍微“有趣/奇怪”的提交,而不是“在一个分支上”。该apply操作查看提交更改的内容,并尝试在您现在所在的任何位置重复它。藏匿处仍然存在(apply保留它),因此您可以更多地查看它,或者确定这是错误的位置apply并以不同的方式重试,或其他任何方式。


任何时候你有一个藏匿处,你都可以git stash show -p用来查看藏匿处的简化版本。(此简化版本仅查看“最终工作树”更改,而不是--index单独恢复的已保存索引更改。)git stash apply没有的命令现在--index只是尝试在您的工作树中进行相同的更改。

即使您已经进行了一些更改,也是如此。该apply命令很乐意将存储应用到修改后的工作树(或至少尝试应用它)。例如,您可以这样做:

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

您可以在此处选择“应用”顺序,选择特定的存储区以按特定顺序应用。但是请注意,每次您基本上是在执行“git merge”时,并且正如合并文档所警告的那样:

不鼓励使用非平凡的未提交更改运行 git merge:虽然可能,但它可能会使您处于在发生冲突时难以退出的状态。

如果您从一棵干净的树开始并且只执行几个git apply操作,则很容易退出:使用git reset --hard回到干净状态,并更改您的apply操作。(这就是为什么我建议首先从干净的工作树开始,对于这些复杂的情况。)


那么最坏的情况呢?

假设你正在做很多高级 Git 的东西,并且你已经做了一个 stash,并且想要git stash apply --index,但是它不再可能应用保存的 stash,--index因为自从你保存它以来分支已经分歧太多了。

这是git stash branch为了什么。

如果你:

  1. 检查您在执行原始操作时所做的确切提交stash,然后
  2. 创建一个新分支,最后
  3. git stash apply --index

重新创建更改的尝试肯定奏效。这就是这样做的。(然后它会在成功应用后丢弃存储。)git stash branch newbranch


最后说几句--index(这到底是什么?)

做什么--index很容易解释,但内部有点复杂:

  • 当您有更改时,您必须在-inggit add之前(或“暂存”)它们。commit
  • 因此,当您运行 时git stash,您可能已经编辑了两个文件foozorg,但只上演了其中一个。
  • 因此,当您要求取回存储时,如果它git addadded东西而不 git add是非添加的东西可能会很好。也就是说,如果你是add-edfoozorg在你做之前没有回来stash,那么拥有完全相同的设置可能会很好。上演过的,应该再上演一次;已修改但未上演的内容应再次修改但未上演。

--index标志 to尝试以这种apply方式进行设置。如果您的工作树是干净的,这通常可以正常工作。但是,如果您的工作树已经有 stuff add-ed,您可以看到这里可能存在一些问题。如果您省略--index,则该apply操作不会尝试保留整个暂存/未暂存设置。相反,它只是调用 Git 的合并机制,使用"stash bag"中的工作树提交。如果您不关心保留分阶段/非分阶段,那么省略--index会使它更容易git stash apply做它的事情。

于 2013-09-25T11:03:52.707 回答
88
git stash pop

会让一切恢复原状

正如评论中所建议的,您可以使用git stash branch newbranch将存储应用到新分支,这与运行相同:

git checkout -b newbranch
git stash pop
于 2013-09-25T10:59:50.690 回答
35

检查您的存储内容:-

git 存储列表

从存储列表中应用特定的存储编号:-

git stash apply stash@{2}

或仅应用第一个存储:-

git stash 弹出

注意: git stash pop 将从您的存储列表中删除存储,而 git stash apply 不会。所以相应地使用它们。

于 2019-06-21T04:02:07.427 回答
34

为了简单起见,您有两个选项来重新应用您的存储:

  1. git stash pop- 恢复到保存状态,但它会从临时存储中删除存储。
  2. git stash apply- 恢复到已保存的状态,并留下存储列表以供以后重用。

您可以在本文中阅读有关git stash的更多详细信息。

于 2018-05-25T07:49:29.247 回答
5

在 Mac 上,这对我有用:

git stash list(查看你所有的存储)

git stash list

git stash apply (只是你想要的存储列表中的数字)

像这样:

git stash apply 1
于 2019-12-17T21:12:27.917 回答
0

您可以使用“git stash”存储未提交的更改,然后使用“git checkout -b”签出到新分支,然后应用隐藏的提交“git stash apply”

于 2020-05-06T04:16:32.117 回答