Git:如何恢复隐藏未提交的更改
我的开发部门有一些未经改变的变化,我把它们用git stash
,但是在那些藏起来的变化中有一些非常重要的变化。 有什么方法可以找回这些变化吗?
此外,我已经在自封的代码文件上做了一些改变。
如果可能的话,是否有机会将隐藏的修改恢复到新的分支?
容易回答的简单问题是git stash apply
只要看看你想要更改的分支,然后git stash apply
。 然后使用git diff
来查看结果。
完成所有更改后, apply
看起来不错,而且您确定不再需要存储 – 然后使用git stash drop
来除去它。
我总是build议使用git stash apply
而不是git stash pop
。 所不同的是, apply
留下的存储周围,以方便重新apply
或查看等,如果pop
可以提取存储,它会立即drop
它,如果你突然意识到你想要把它提取到其他地方(在不同的分支),或者用--index
或者其他的东西,那不是那么容易。 如果你apply
, 你可以select何时drop
。
虽然这是一个很小的方法,对于一个新手来说,它应该是大致相同的。 (你可以跳过这一切!)
如果你正在做更高级或更复杂的事情呢?
至less有三四种不同的“使用git存储方式”,就像它一样。 以上是“方式一”,“方式一”:
-
你从一个干净的分支开始,正在做一些改变,然后意识到你在错误的分支中做着它们。 你只需要把你现在所做的改变和“移动”到另一个分支。
如上所述,这是简单的情况。 运行
git stash save
(或普通的git stash
,同样的事情)。 检查出另一个分支并使用git stash apply
。 这得到了git在你以前的改变,使用git的相当强大的合并机制合并。 仔细检查结果 (使用git diff
),看看你是否喜欢它们,如果你这样做,使用git stash drop
来放置存储。 你完成了! -
你开始了一些变化,并把它们藏起来。 然后,你切换到另一个分支,并开始更多的变化,忘记你有藏起来的。
现在你想要保留,甚至移动这些变化, 并且应用你的隐藏。
事实上你可以把
git stash save
再git stash save
一次,因为git stash
会产生一个“堆栈”的变化。 如果你这样做,你有两个stash
,一个只是被称为stash
– 但你也可以写stash@{0}
和一个拼写stash@{1}
。 使用git stash list
(在任何时候)看到他们全部。 最新的总是最低的编号。 当你git stash drop
,它会丢弃最新的东西,而stash@{1}
会移动到栈顶。 如果您还有更多的话,stash@{2}
stash@{1}
将变成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
上被命名为WIP on branch
)。 -
(Extra-advanced)在运行
git stash save
之前,你已经使用了git stash save -p
,或者仔细地用git add
-ed和/或git rm
-ed你的代码的特定位。 在隐藏的索引/暂存区域中有一个版本,而在工作树中有另一个(不同的)版本。 你想保留所有这一切。 所以现在你使用git stash apply --index
,并且有时会失败:Conflicts in index. Try without --index.
-
您正在使用
git stash save --keep-index
以testing“将承诺什么”。 这个超出了这个答案的范围。 请参阅此其他StackOverflow答案 。
对于复杂的情况,我build议首先在一个“干净的”工作目录中,通过提交你现在所做的任何更改(如果你喜欢的话,在一个新的分支上)。 这样,你所应用的“某个地方”就没有其他的东西了,你只需要尝试一下变化:
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
它,并尝试不同的方式,或者不pipe。
任何时候你有一个藏匿的,你可以使用git stash show -p
来看看git stash show -p
在里面的简化版本。 (这个简化的版本只能看到“最终工作树”的变化, 而不是保存下来的索引变化 – 索引--index
恢复) --index
git stash apply
,没有--index
,只是试图在工作中做相同的改变,目录。
即使您已经有一些变化,情况也是如此。 apply
命令很乐意将一个存储器应用到一个修改的工作目录(至less,试图应用它)。 你可以,例如,这样做:
git stash apply stash # apply top of stash stack git stash apply stash@{1} # and mix in next stash stack entry too
您可以在这里select“申请”命令,挑出特定的包装以特定顺序应用。 但是,请注意,每次你基本上正在做一个“混帐合并”,并作为合并文件警告:
不鼓励git合并非重要的未提交的变更:尽pipe可能,但可能会让你处于一个冲突情况下很难退出的状态。
如果你从一个干净的目录开始,只做几个git apply
操作,很容易退出:使用git reset --hard
返回到clean状态,并改变你的apply
操作。 (这就是为什么我build议首先从干净的工作目录开始,对于这些复杂的情况。)
那最糟糕的情况呢?
假设你正在做很多先进的Git Stuff,并且你已经做了一个存储,并且想要git stash apply --index
,但是不能再使用--index
来应用保存的存储,因为分支已经发散了自从你保存它以来太多了。
这是git stash branch
的用途。
如果你:
- 那么当你做原始
stash
,检查你的确切提交 - 创build一个新的分支,最后
-
git stash apply --index
重新创build更改的尝试肯定会奏效。 这是git stash branch newbranch
所做的。 (然后,它成功地应用了,然后它就下降了。)
关于--index
一些最后的话(它到底是什么?)
– --index
做的很简单,但内部有些复杂:
- 当你有改变时,你必须在
commit
之前git add
(或“阶段”)他们。 - 因此,当你运行
git stash
,你可能已经编辑了foo
和zorg
这两个文件,但是只能执行其中的一个。 - 所以当你要求隐藏的时候,如果它
git add
了add
东西而不是git add
了未添加的东西,那可能会很好。 也就是说,如果你在stash
之前add
edfoo
而不是zorg
,那么完成相同的设置可能会很好。 什么上演,应该再次上演; 什么修改,但不上演,应该再次修改,但不上演。
要apply
的--index
标志尝试设置这种方式。 如果你的工作树是干净的,这通常是正常的。 如果你的工作树已经有东西add
,但是,你可以看到这里可能会有一些问题。 如果你没有使用--index
, apply
操作不会保留整个stage / unstaged的设置。 相反,它只是调用git的合并机制,使用“隐藏包”中的工作树提交。 如果你不关心保持上演/未上架,留下 – --index
使得它更容易git stash apply
做它的事情。
git stash pop
将一切都恢复原状
如注释中所build议的那样,您可以使用git stash branch newbranch
将存储应用到新的分支,这与运行相同:
git checkout -b newbranch git stash pop