如何从 git stash 中提取单个文件(或对文件的更改)?

发布于 2024-07-26 02:23:16 字数 43 浏览 5 评论 0原文

是否可以从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

忘东忘西忘不掉你 2024-08-02 02:23:16

git stash< /a> 联机帮助页您可以阅读(在“讨论”部分,“选项”描述之后):

存储表示为提交,其树记录了提交的状态
工作目录,其第一个父目录是 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-parse 手册页rev^! 语法的解释,在“指定范围”部分)。

同样,要回答您的问题,您可以使用 git checkout 签出单个文件存储的(请注意,这将不会git stash apply那样合并存储,这意味着对文件所做的任何更改都将被覆盖):

$ git checkout stash@{0} -- <filename>

或将其保存在另一个文件名:

$ git show stash@{0}:<full filename>  >  <newfile>

$ git show stash@{0}:./<relative filename> > <newfile>

注意这里的<完整文件名>是相对于项目顶级目录的文件的完整路径名(认为:相对于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:

A stash is represented as a commit whose tree records the state of the
working directory, and its first parent is the commit at HEAD when the
stash was created.

So you can treat stash (e.g. stash@{0} is first / topmost stash) as a merge commit, and use:

$ git diff stash@{0}^1 stash@{0} -- <filename>

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) because stash@{0} / refs/stash is a merge commit, and we have to tell git which parent we want to diff against. More cryptic:

$ git diff stash@{0}^! -- <filename>

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):

$ git checkout stash@{0} -- <filename>

or to save it under another filename:

$ git show stash@{0}:<full filename>  >  <newfile>

or

$ git show stash@{0}:./<relative filename> > <newfile>

(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}'.

山田美奈子 2024-08-02 02:23:16
git checkout stash@{0} -- <filename>

注意:

  1. 警告:这将不会合并文件——对文件的任何现有更改都将被覆盖。

  2. 确保在 -- 周围留有空格。

  3. 如果您想要从中获取文件的存储不是最新的,请将 0 替换为您的特定存储编号。 (要列出存储,请运行git stash list。)

基于 Jakub Narębski 的回答 - 较短版本

git checkout stash@{0} -- <filename>

Notes:

  1. Warning: this will not merge the file—any existing changes to the file will be overwritten.

  2. Make sure you put spaces around the --.

  3. If the stash you want the file from isn't the latest one, replace 0 with your specific stash number. (To list stashes, run git stash list.)

Based on Jakub Narębski's answer -- Shorter version

守护在此方 2024-08-02 02:23:16

如果您使用 git stash apply 而不是 git stash pop ,它会将存储应用到您的工作树,但仍保留存储。

完成此操作后,您可以添加/提交所需的文件,然后重置其余更改。

If you use git stash apply rather than git 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.

权谋诡计 2024-08-02 02:23:16

编辑:参见cambunctious的答案,这基本上是我现在更喜欢的,因为它只使用更改在藏匿处,而不是将它们与您当前的状态进行比较。 这使得操作具有附加性,自创建存储以来撤消已完成工作的机会大大减少。

要以交互方式执行此操作,您首先要做

git diff stash^! -- path/to/relevant/file/in/stash.ext perhaps/another/file.ext > my.patch

...然后在文本编辑器中打开补丁文件,根据需要进行更改,然后 do

git apply < my.patch

cambunctious 的答案通过将一个命令直接传递到另一个命令来绕过交互性,如果您知道自己想要的话,这很好隐藏中的所有更改。 您可以将 stash^! 编辑为具有所需累积更改的任何提交范围(但首先检查差异的输出)。

如果应用补丁/差异失败,您可以将最后一个命令更改为 git apply --reject ,这将进行所有可以进行的更改,并将 .rej 文件保留在存在的位置无法解决的冲突。 然后可以使用 wiggle.rej 文件>,如下所示:

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,并提供应用分支之间的所有差异。 要仅从单个提交/存储中获取更改,请查看 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

git diff stash^! -- path/to/relevant/file/in/stash.ext perhaps/another/file.ext > my.patch

...then open the patch file in a text editor, alter as required, then do

git apply < my.patch

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 using wiggle, like so:

wiggle --replace path/to/relevant/file/in/stash.ext{,.rej}

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:

cd /usr/local/src/
git clone git://git.neil.brown.name/wiggle
cd wiggle/
git checkout v1.3
make install

Previous solution: There is an easy way to get changes from any branch, including stashes:

$ git checkout --patch stash@{0} path/to/file

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 from git stash list, if you have more than one. Note that this is like diff, and offers to apply all differences between the branches. To get changes from only a single commit/stash, have a look at git cherry-pick --no-commit.

妖妓 2024-08-02 02:23:16

简短回答

要查看整个文件: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>

几味少女 2024-08-02 02:23:16

使用以下命令将对存储中的文件的更改应用到您的工作树。

git diff stash^! -- <filename> | git apply

这通常比使用 git checkout 更好,因为您不会丢失自创建存储以来对文件所做的任何更改。

Use the following to apply the changes to a file in a stash to your working tree.

git diff stash^! -- <filename> | git apply

This is generally better than using git checkout because you won't lose any changes you made to file since you created the stash.

一梦浮鱼 2024-08-02 02:23:16

您可以使用“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.

笑,眼淚并存 2024-08-02 02:23:16

对于 VS Code 用户,有一种方法。 确保安装了 GitLens 扩展程序。

  1. 转到SOURCE CONTROL 选项卡,
  2. 单击STASHES
  3. 您将能够看到可用的藏品。
  4. 单击所需的存储。
  5. 右键单击要取消存储的所需文件。
  6. 您将获得 2 个选项:应用更改恢复(签出)。 您可以单击任何选项,如果您选择应用更改,您将在更改下看到您的文件;如果您选择,您将在分阶段更改下看到您的文件恢复(结帐)

For VS Code users, there is one method. Make sure to have GitLens extension installed.

  1. Go on SOURCE CONTROL tab
  2. Click on STASHES.
  3. You will be able to see available stashes.
  4. Click on the desired stash.
  5. Right click on the desired file which you want to unstash.
  6. You will get 2 options, Apply Changes and Restore (Checkout). You can click any of the options and you will get your file under Changes if you choose Apply Changes or Staged Changes if you choose Restore (Checkout).

unstash files from stash

久夏青 2024-08-02 02:23:16

最容易理解的概念(尽管可能不是最好的)是您更改了三个文件并且您想要存储一个文件。

如果您使用 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 then git 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 run git stash apply again, taking advantage ofthe fact that git stash apply doesn't clear the diff from the stash stack.

转角预定愛 2024-08-02 02:23:16

如果隐藏的文件需要与当前版本合并,请使用以前使用 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 a git 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文