我的开发分支中有一些未提交的更改,我使用 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 的新手来说,应该差不多。 (你可以跳过所有其他的!)
如果您正在做更高级或更复杂的事情怎么办?
至少有三四种不同的“使用 git stash 的方法”。以上是“方式1”,“简单方式”:
你从一个干净的分支开始,正在进行一些更改,然后意识到你在错误的分支中进行了这些更改。您只想将现有的更改“移动”到另一个分支。
这是简单的情况,如上所述。运行 git stash save
(或普通的 git stash
,同样的事情)。检查另一个分支并使用 git stash apply
。这让 Git 使用 Git 相当强大的合并机制来合并您之前的更改。 仔细检查结果(使用 git diff
)看看您是否喜欢它们,如果喜欢,请使用 git stash drop
删除存储。你完成了!
您开始了一些更改并将它们隐藏起来。然后你切换到另一个分支并开始了更多的更改,忘记了你有隐藏的那些。
现在您想保留甚至移动这些更改,并应用您的存储。
实际上,您可以再次git stash save
,因为 git stash
会进行“堆栈”更改。如果你这样做,你有两个 stashes,一个叫 stash
——但你也可以写 stash@{0}
——一个拼写为 stash@
。使用 git stash save
git stash list
(随时)查看所有内容。最新的总是编号最低的。当您 git stash drop
时,它会丢弃最新的,而之前为 stash@
的将移至堆栈顶部。如果你有,甚至更多,那个是 git stash save
stash@{2}
变成 stash@
,依此类推。
git stash save
您也可以先apply
,然后再drop
一个特定的存储:git stash apply stash@
,依此类推。删除特定的存储只会重新编号编号较高的存储。同样,没有数字的也是drop
stash@{0}
。
如果你堆积了很多存储,它会变得相当混乱(我想要的存储是 stash@{7}
还是 stash@{4}
?等等,我刚刚推了另一个,现在它们是 8 和 5?)。我个人更喜欢将这些更改转移到新分支,因为分支有名称,而且 cleanup-attempt-in-December
对我来说比 stash@{12}
更重要。 (git stash
命令需要一个可选的保存消息,这些可以提供帮助,但不知何故,我所有的存储最终都命名为 WIP on branch
。)
(超高级)在运行 git stash save -p 之前,您已经使用了 git stash save -p,或者仔细 git add-ed 和/或 git rm-ed 代码的特定位。您在隐藏的索引/暂存区域中有一个版本,在工作树中有另一个(不同的)版本。你想保留这一切。所以现在你使用 git stash apply --index,有时会失败:索引冲突。尝试不使用--index。您正在使用 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
要记住的主要事情是“存储”是一个提交,它只是一个稍微“有趣/奇怪”的提交,而不是“在一个分支上”。 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 东西,并且您已经创建了一个存储,并且想要 git stash apply --index
,但是不再可能使用 --index
应用保存的存储,因为自从你保存它的时间。
这就是 git stash branch
的用途。
如果你:
检查您在执行原始存储时所做的确切提交,然后创建一个新分支,最后 git stash apply --index
重新创建更改的尝试肯定会奏效。这就是 git stash branch newbranch
的作用。 (然后它会在成功应用后丢弃存储。)
关于 --index 的一些最后的话(到底是什么?)
--index
的作用很容易解释,但内部有点复杂:
当您有更改时,您必须在提交之前 git add (或“暂存”)它们。
因此,当您运行 git stash 时,您可能已经编辑了文件 foo 和 zorg,但只暂存了其中一个。
因此,当您要求取回存储时,如果它 git 添加添加的东西而不是 git 添加未添加的东西可能会很好。也就是说,如果您在进行 stash 之前添加了 foo 而不是 zorg,那么拥有完全相同的设置可能会很好。上演过的,应该再上演一次;已修改但未上演的内容应再次修改但未上演。
apply
的 --index
标志试图以这种方式进行设置。如果您的工作树是干净的,这通常可以正常工作。但是,如果您的工作树已经包含 add
-ed,您可以看到这里可能存在一些问题。如果您省略 --index
,则 apply
操作不会尝试保留整个分阶段/非分阶段设置。相反,它只是调用 Git 的合并机制,使用 "stash bag" 中的工作树提交。如果您不关心保留分阶段/非分阶段,则省略 --index
可以让 git stash apply
更轻松地完成它的工作。
git stash pop
会让一切恢复原状
正如评论中所建议的,您可以使用 git stash branch newbranch
将存储应用到新分支,这与运行相同:
git checkout -b newbranch
git stash pop
git stash branch newbranch
确实会这样做;但请注意,它会创建新分支,其父级设置为 stash
完成时的 HEAD
提交。换句话说,这是为了当你在长时间的黑客会议或其他什么之后回来时,盯着那些乱七八糟的东西,然后决定“我应该把它放在一个分支上,而不是藏起来”:-)
检查您的存储内容:-
git 存储列表
从存储列表中应用特定的存储编号:-
git stash apply stash@{2}
或仅应用第一个存储:-
git stash 弹出
注意: git stash pop 将从您的存储列表中删除存储,而 git stash apply 不会。所以相应地使用它们。
为了简单起见,您有两个选项来重新应用您的存储:
git stash pop - 恢复到保存状态,但它会从临时存储中删除存储。 git stash apply - 恢复到保存的状态并留下存储列表以供以后重用。
您可以在本文中阅读有关 git stashes 的更多详细信息。
在 Mac 上,这对我有用:
git stash list(查看你所有的存储)
git stash list
git stash apply (只是你想要的存储列表中的数字)
像这样:
git stash apply 1
您可以使用以下方法存储未提交的更改:
git stash
然后使用以下命令签出新分支:
git checkout -b
然后应用隐藏的提交:
git stash apply
不定期副业成功案例分享
git stash pop
?或者您的意思是:您编辑了一些文件,但还没有再次运行git stash
?或者你的意思完全不同?apply
隐藏之前提交您现在拥有的内容。您不必必须执行此操作,但它使您查看起来更简单。您可以稍后使用rebase -i
将多个提交压缩在一起,或者挑选特定的更改或其他任何内容。git stash apply --index
(记住两个破折号)。如果您省略--index
,没什么大不了的;--index
的唯一要点是保持分阶段/非分阶段设置。 (您可能一开始没有任何特殊设置。)然后是git status
等,并根据需要添加/提交等。当(且仅当)您完成所有存储时,使用git stash drop
来丢弃它。drop
或pop
)存储,您在提交时始终可以安全地保存原始存储代码,因为存储是提交!如果您想准确地取回它,但在分支上,请使用git stash branch
(参见上面的那部分,或 Shunya's answer 中的 Pro Git book)。然后,您可以git checkout
该分支,或git cherry-pick
该分支的提交,等等。