如何从 git stash 中提取单个文件(或对文件的更改)?
是否可以从 git 存储中提取单个文件或文件的差异,而不弹出存储更改集?
Is it possible to extract a single file or diff of a file from a git stash without popping the stash changeset off?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
在 git stash< /a> 联机帮助页您可以阅读(在“讨论”部分,“选项”描述之后):
因此,您可以将存储(例如
stash@{0}
是第一个/最上面的存储)视为合并提交,并使用:说明:
stash@{0}^1
表示给定存储的第一个父级,如上面的解释所述,是存储更改的提交。 我们使用这种形式的“git diff”(有两次提交),因为stash@{0}
/refs/stash
是合并提交,我们必须告诉 git 哪一个提交我们想要与之比较的父母。 更神秘:应该也可以工作(请参阅 git rev-parse 手册页
rev^!
语法的解释,在“指定范围”部分)。同样,要回答您的问题,您可以使用 git checkout 签出单个文件存储的(请注意,这将不会像
git stash apply
那样合并存储,这意味着对文件所做的任何更改都将被覆盖):或将其保存在另一个文件名:
或
(注意这里的<完整文件名>是相对于项目顶级目录的文件的完整路径名(认为:相对于
stash@{0}
))。您可能需要保护
stash@{0}
免受 shell 扩展,即使用"stash@{0}"
或'stash@{0}'.
On the git stash manpage you can read (in the "Discussion" section, just after "Options" description) that:
So you can treat stash (e.g.
stash@{0}
is first / topmost stash) as a merge commit, and use:Explanation:
stash@{0}^1
means the first parent of the given stash, which as stated in the explanation above is the commit at which changes were stashed away. We use this form of "git diff" (with two commits) becausestash@{0}
/refs/stash
is a merge commit, and we have to tell git which parent we want to diff against. More cryptic:should also work (see git rev-parse manpage for explanation of
rev^!
syntax, in "Specifying ranges" section).Likewise, to answer your question, you can use git checkout to check a single file out of the stash (note that this will not merge the stash like
git stash apply
does—that means any changes made to the file will be overwritten):or to save it under another filename:
or
(note that here <full filename> is full pathname of a file relative to top directory of a project (think: relative to
stash@{0}
)).You might need to protect
stash@{0}
from shell expansion, i.e. use"stash@{0}"
or'stash@{0}'
.注意:
警告:这将不会合并文件——对文件的任何现有更改都将被覆盖。
确保在
--
周围留有空格。如果您想要从中获取文件的存储不是最新的,请将
0
替换为您的特定存储编号。 (要列出存储,请运行git stash list
。)基于 Jakub Narębski 的回答 - 较短版本
Notes:
Warning: this will not merge the file—any existing changes to the file will be overwritten.
Make sure you put spaces around the
--
.If the stash you want the file from isn't the latest one, replace
0
with your specific stash number. (To list stashes, rungit stash list
.)Based on Jakub Narębski's answer -- Shorter version
如果您使用 git stash apply 而不是 git stash pop ,它会将存储应用到您的工作树,但仍保留存储。
完成此操作后,您可以
添加
/提交
所需的文件,然后重置其余更改。If you use
git stash apply
rather thangit stash pop
, it will apply the stash to your working tree but still keep the stash.With this done, you can
add
/commit
the file that you want and then reset the remaining changes.编辑:参见cambunctious的答案,这基本上是我现在更喜欢的,因为它只使用更改在藏匿处,而不是将它们与您当前的状态进行比较。 这使得操作具有附加性,自创建存储以来撤消已完成工作的机会大大减少。
要以交互方式执行此操作,您首先要做
...然后在文本编辑器中打开补丁文件,根据需要进行更改,然后 do
cambunctious 的答案通过将一个命令直接传递到另一个命令来绕过交互性,如果您知道自己想要的话,这很好隐藏中的所有更改。 您可以将
stash^!
编辑为具有所需累积更改的任何提交范围(但首先检查差异的输出)。如果应用补丁/差异失败,您可以将最后一个命令更改为 git apply --reject ,这将进行所有可以进行的更改,并将 .rej 文件保留在存在的位置无法解决的冲突。 然后可以使用
wiggle
.rej 文件>,如下所示:这将解决冲突,或者为您提供从合并中获得的冲突标记。
如果您的发行版没有
wiggle
,您可以直接构建它:以前的解决方案: 有一种简单的方法可以从任何分支(包括存储)获取更改:
您可以省略如果您想修补多个部分,则需要指定文件规范。 或者省略补丁(但不省略路径)以获取对单个文件的所有更改。 如果您有多个,请将
0
替换为git stash list
中的存储编号。 请注意,这类似于diff
,并提供应用分支之间的所有差异。 要仅从单个提交/存储中获取更改,请查看 gitcherry-pick --no-commit。Edit: See cambunctious's answer, which is basically what I now prefer because it only uses the changes in the stash, rather than comparing them to your current state. This makes the operation additive, with much less chance of undoing work done since the stash was created.
To do it interactively, you would first do
...then open the patch file in a text editor, alter as required, then do
cambunctious's answer bypasses the interactivity by piping one command directly to the other, which is fine if you know you want all changes from the stash. You can edit the
stash^!
to be any commit range that has the cumulative changes you want (but check over the output of the diff first).If applying the patch/diff fails, you can change the last command to
git apply --reject
which makes all the changes it can, and leaves.rej
files where there are conflicts it can't resolve. The.rej
files can then be applied usingwiggle
, like so:This will either resolve the conflict, or give you conflict markers that you'd get from a merge.
If your distro doesn't have
wiggle
, you can just build it:Previous solution: There is an easy way to get changes from any branch, including stashes:
You may omit the file spec if you want to patch in many parts. Or omit patch (but not the path) to get all changes to a single file. Replace
0
with the stash number fromgit stash list
, if you have more than one. Note that this is likediff
, and offers to apply all differences between the branches. To get changes from only a single commit/stash, have a look atgit cherry-pick --no-commit
.简短回答
要查看整个文件:
git show stash@{0}:
要查看差异:
git diff stash@{0}^1 stash@{0} - - <文件名>
Short answer
To see the whole file:
git show stash@{0}:<filename>
To see the diff:
git diff stash@{0}^1 stash@{0} -- <filename>
使用以下命令将对存储中的文件的更改应用到您的工作树。
这通常比使用 git checkout 更好,因为您不会丢失自创建存储以来对文件所做的任何更改。
Use the following to apply the changes to a file in a stash to your working tree.
This is generally better than using
git checkout
because you won't lose any changes you made to file since you created the stash.您可以使用“
git show stash@{0}
”(或任何存储的编号;请参阅“git stash list”)获取存储的差异。 提取单个文件的差异部分很容易。You can get the diff for a stash with "
git show stash@{0}
" (or whatever the number of the stash is; see "git stash list"). It's easy to extract the section of the diff for a single file.对于 VS Code 用户,有一种方法。 确保安装了 GitLens 扩展程序。
SOURCE CONTROL
选项卡,STASHES
。应用更改
和恢复(签出)
。 您可以单击任何选项,如果您选择应用更改
,您将在更改
下看到您的文件;如果您选择,您将在
。分阶段更改
下看到您的文件恢复(结帐)For VS Code users, there is one method. Make sure to have GitLens extension installed.
SOURCE CONTROL
tabSTASHES
.Apply Changes
andRestore (Checkout)
. You can click any of the options and you will get your file underChanges
if you chooseApply Changes
orStaged Changes
if you chooseRestore (Checkout)
.最容易理解的概念(尽管可能不是最好的)是您更改了三个文件并且您想要存储一个文件。
如果您使用
git stash
将它们全部存储起来,则git stash apply
将它们再次带回来,然后对相关文件进行git checkout fc
以有效地重置它。当您想要取消存储该文件时,请执行
git reset --hard
,然后再次运行git stash apply
,利用git stash apply
的事实code> 不会清除存储堆栈中的差异。The simplest concept to understand, although maybe not the best, is you have three files changed and you want to stash one file.
If you do
git stash
to stash them all,git stash apply
to bring them back again and thengit checkout f.c
on the file in question to effectively reset it.When you want to unstash that file run do a
git reset --hard
and then rungit stash apply
again, taking advantage ofthe fact thatgit stash apply
doesn't clear the diff from the stash stack.如果隐藏的文件需要与当前版本合并,请使用以前使用 diff 的方法。 否则,您可以使用 git pop 来取消存储它们,使用 git add fileWantToKeep 来暂存文件,然后执行 git stash save --keep-index 。 ,用于存放除舞台上的内容之外的所有内容。
请记住,这种方式与以前的方式的区别在于它从存储中“弹出”文件。 前面的答案保留它
git checkout stash@{0} --
因此它可以根据您的需要进行。If the stashed files need to merge with the current version so use the previous ways using diff. Otherwise you might use
git pop
for unstashing them,git add fileWantToKeep
for staging your file, and do agit stash save --keep-index
, for stashing everything except what is on stage.Remember that the difference of this way with the previous ones is that it "pops" the file from stash. The previous answers keep it
git checkout stash@{0} -- <filename>
so it goes according to your needs.