协慌网

登录 贡献 社区

如何恢复隐藏的未提交的更改

我在开发分支中进行了一些未提交的更改,并使用git stash进行了隐藏,但是其中一些更改在这些已隐藏的更改中非常重要。有什么办法找回这些更改吗?

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

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

答案

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

只需签出要进行更改的分支,然后git stash apply 。然后使用git diff查看结果。

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

我总是建议使用git stash apply而不是git stash pop 。区别在于apply留下存储区,以便于重试apply或查看等操作。如果pop能够提取存储区,它也会立即drop其删除,并且如果您突然意识到自己想要要将其提取到其他位置(在不同的分支中),或者使用--index或类似的方法,并不是那么容易。如果您apply ,则可以选择何时drop

但是,无论哪种方式,它都相当次要,对于 git 的新手来说,它应该大致相同。 (并且您可以跳过所有其他步骤!)


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

至少有 3 或 4 种不同的 “使用 git stash 的方式”。上面是针对 “方法 1” 的 “简单方法”:

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

    如上所述,这是简单的情况。运行git stash save (或普通的git stash ,同样的东西)。签出另一个分支,并使用git stash apply 。使用 git 强大的合并机制,可以使 git 合并到您的早期更改中。仔细检查结果(使用git diff )以查看是否喜欢它们,如果愿意,请使用git stash drop放下隐藏物。你完成了!

  2. 您开始了一些更改并将其隐藏。然后,您切换到另一个分支并开始更多更改,而忘记了已藏匿的分支。

    现在,您要保留甚至移动这些更改,并也应用存储。

    实际上,您可以git stash save ,因为git stash会使更改 “堆叠”。如果这样做,则有两个stash ,一个仅称为存储 - 但您也可以编写stash@{0} - 和一个拼写的stash@{1} 。使用git stash list (随时)查看它们。最新的始终是编号最小的。当您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 Decempt 对我而言比stash@{12}得多。 ( git stash命令采用了可选的保存消息,它们可以提供帮助,但是以某种方式,我所有的存储都只是WIP on branch 。)

  3. (高级)您已经使用git stash save -p ,或者git stash save git add -ed 和 / 或git rm -ed 代码的特定位。在隐藏的索引 / 暂存区中有一个版本,在工作树中有另一个(不同的)版本。您要保留所有这些。因此,现在您使用git stash apply --index ,有时会失败,并显示以下信息:

    Conflicts in index.  Try without --index.
  4. 您正在使用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 new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

要记住的主要事情是,“存储”一个提交,只是一个稍微 “有趣 / 怪异” 的提交,而不是 “在分支上”。 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 并进行重要的,未提交的更改:虽然可能,但可能会导致您陷入冲突中难以退缩的状态。

如果您从一个 clean 目录开始并且仅执行几个git apply操作,则很容易git reset --hard返回到 clean 状态,并更改您的apply操作。 (因此,对于这些复杂的情况,我建议首先从一个干净的工作目录开始。)


那在最坏的情况下呢?

假设您正在做很多高级 Git Stuff,并且已经做了一个存储,并且想要git stash apply --index ,但是不再可以用--index来应用保存的存储,因为分支已经分开自您保存时间以来过多。

这就是git stash branch的用途。

如果你:

  1. 查看执行原始stash时的确切提交,然后
  2. 创建一个新的分支,最后
  3. git stash apply --index

重新创建更改的尝试肯定奏效。这就是git stash branch <em>newbranch</em>所做的。 (然后,由于成功应用了存储,它会删除该存储。)


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

--index作用很容易解释,但内部有点复杂:

  • 进行更改后,必须commit git add (或 “登台”)它们。
  • 因此,当您运行git stash ,您可能已经编辑了文件foozorg ,但仅上演了其中一个。
  • 因此,当您要求收回存储时,如果它git add s add ed 东西而没有git add未添加的东西,则可能会很好。也就是说,如果在执行stash add ed foo而不zorg ,则最好具有完全相同的设置。上演过的,应该再次上演;已修改但未上演的内容应再次修改但不可上演。

apply--index标志会尝试以这种方式进行设置。如果您的工作树是干净的,通常就可以了。但是,如果您的工作树已经add东西,那么您可以在这里看到可能有一些问题。如果省略--index ,则apply操作不会尝试保留整个暂存 / 未暂存的设置。相反,它只是使用 “存储袋” 中的工作树提交来调用 git 的合并机制。如果您不关心保留暂存 / 未暂存,则省略--index可以使git stash apply更容易执行此操作。

git stash pop

将一切恢复原状

如注释中所建议,您可以使用git stash branch newbranch将隐藏应用到新分支,这与运行相同:

git checkout -b newbranch
git stash pop

为简单起见,您有两种选择可以重新应用存储:

  1. git stash pop恢复到保存状态,但会从临时存储中删除该存储。
  2. git stash apply恢复到保存状态,并保留存储列表,以备日后重用。

您可以在本文中详细了解有关git stash 的信息。