是否可以从 git stash 中提取单个文件或文件的差异而不弹出 stash 变更集?
9 回答
在git stash 手册页上,您可以阅读(在“讨论”部分中,就在“选项”描述之后):
存储被表示为一个提交,其树记录工作目录的状态,其第一个父级是创建存储时在 HEAD 的提交。
因此,您可以将存储(例如stash@{0}
,第一个/最顶层存储)视为合并提交,并使用:
$ git diff stash@{0}^1 stash@{0} -- <filename>
解释:stash@{0}^1
表示给定存储的第一个父级,如上面的解释中所述,是隐藏更改的提交。我们使用这种形式的“git diff”(有两个提交),因为stash@{0}
/refs/stash
是一个合并提交,我们必须告诉 git 我们想要比较哪个父级。更神秘:
$ git diff stash@{0}^! -- <filename>
也应该可以工作(请参阅git rev-parserev^!
手册页以了解“指定范围”部分中的语法解释)。
同样,您可以使用git checkout从存储中检查单个文件:
$ git checkout stash@{0} -- <filename>
或将其保存在另一个文件名下:
$ git show stash@{0}:<full filename> > <newfile>
或者
$ git show stash@{0}:./<relative filename> > <newfile>
(请注意,这里的 <full filename> 是相对于项目顶级目录的文件的完整路径名(认为:相对于stash@{0}
))。
您可能需要防止stash@{0}
外壳扩展,即使用"stash@{0}"
or 'stash@{0}'
。
如果您使用git stash apply
而不是git stash pop
,它会将存储应用到您的工作树,但仍保留存储。
完成此操作后,您可以add
/commit
您想要的文件,然后重置剩余的更改。
编辑:请参阅cambunctious 的答案,这基本上是我现在更喜欢的,因为它只使用存储中的更改,而不是将它们与您当前的状态进行比较。这使得操作具有附加性,自创建存储以来撤消已完成工作的机会要小得多。
要以交互方式执行此操作,您首先要执行
git diff stash^! -- path/to/relevant/file/in/stash.ext perhaps/another/file.ext > my.patch
...然后在文本编辑器中打开补丁文件,根据需要进行更改,然后执行
git apply < my.patch
cambunctious 的答案通过将一个命令直接传递给另一个命令来绕过交互性,如果您知道要从存储中进行所有更改,这很好。您可以将其编辑为stash^!
具有所需累积更改的任何提交范围(但首先检查差异的输出)。
如果应用补丁/差异失败,您可以更改最后一个命令,git apply --reject
使其可以进行所有更改,并将文件留.rej
在无法解决的冲突中。然后.rej
可以使用 应用文件wiggle
,如下所示:
wiggle --replace path/to/relevant/file/in/stash.ext{,.rej}
这将解决冲突,或者为您提供从合并中获得的冲突标记。
如果您的发行版没有wiggle
,您可以构建它:
cd /usr/local/src/
git clone git://git.neil.brown.name/wiggle
cd wiggle/
git checkout v1.3
make install
以前的解决方案:有一种简单的方法可以从任何分支获取更改,包括存储:
$ git checkout --patch stash@{0} path/to/file
如果你想在很多部分打补丁,你可以省略文件规范。或者省略补丁(但不是路径)以获取对单个文件的所有更改。如果您有多个,请替换0
为 中的存储编号。git stash list
请注意,这类似于diff
, 并提供应用分支之间的所有差异。要仅从单个提交/存储中获取更改,请查看git cherry-pick --no-commit
.
$ git checkout stash@{0} -- <filename>
笔记:
确保在“--”和文件名参数之后放置空格
将零 (0) 替换为您的特定存储编号。要获取存储列表,请使用:
git stash list
基于Jakub Narębski 的回答——短版
简短的回答
要查看整个文件:git show stash@{0}:<filename>
要查看差异:git diff stash@{0}^1 stash@{0} -- <filename>
使用以下命令将更改应用到存储中的文件到您的工作树。
git diff stash^! -- <filename> | git apply
这通常比使用更好,git checkout
因为您不会丢失自创建存储以来对文件所做的任何更改。
git show stash@{0}
您可以使用“ ”(或任何存储数量;请参阅“git stash list”)获取存储的差异。提取单个文件的差异部分很容易。
要理解的最简单的概念,虽然可能不是最好的,是您更改了三个文件并且您想要存储一个文件。
如果您确实git stash
将它们全部存储起来,git stash apply
请将它们再次带回来,然后git checkout f.c
在有问题的文件上有效地重置它。
当您想取消存储该文件时,请执行 agit reset --hard
然后git stash apply
再次运行,利用git stash apply
不会从存储堆栈中清除差异的事实。
如果隐藏的文件需要与当前版本合并,请使用之前使用 diff 的方法。否则,您可能会使用git pop
取消存储它们,git add fileWantToKeep
暂存文件,并使用git stash save --keep-index
, 存储除舞台上的内容之外的所有内容。请记住,这种方式与以前的不同之处在于它从 stash 中“弹出”文件。以前的答案git checkout stash@{0} -- <filename>
会保留它,以便根据您的需要进行。