'git stash apply' 交互模式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28195778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 10:43:14  来源:igfitidea点击:

'git stash apply' with Interactive Mode

gitgit-stashchunksinteractive-mode

提问by Kamafeather

I have a serie of files into a stash (stash{0}) and I would like to git applyjustsome parts/hunks of these files (usually known as Interactive mode).

我有文件的意甲成藏(stash{0}),我想git apply只是一些零件/这些文件(通常被称为帅哥交互模式)。

Is it possible?

是否可以?

I've seen that is possible to perform a

我已经看到可以执行

git stash save -p 'Stash name'

but it seems not possible to do

但似乎不可能做到

git stash apply -p 'Stash name'

Do you know a way to achieve it?

你知道实现它的方法吗?

回答by LeoRochael

Is it possible?

是否可以?

Yes it is!

是的!

git checkout -p stash@{0}

Where you can replace the 0in stash@{0}with the index of the stash you want to apply.

您可以将0in替换为stash@{0}您要应用的存储的索引。

Use git stash listand git show -p stash@{n}if unsure which nis the stash you want to apply.

使用git stash listgit show -p stash@{n}如果不确定哪个n是您要应用的存储。

Don't forget to git stash drop stash@{n}when you know don't need that stash anymore, since git checkoutobviously will not drop the stash for you.

不要忘记git stash drop stash@{n}当你知道不再需要那个藏匿处时,因为git checkout显然不会为你放弃藏匿处。

Why does it work?

为什么有效?

The key is to realize that stashes are, in essence, referencesto commitsjust like tags and branches.

关键是要意识到 stash 本质上是对提交的引用,就像标签和分支一样。

Indeed, they're stored in .git/refs/stash, one line per stash hash.

事实上,它们存储在.git/refs/stash, 每个存储哈希一行。

Caveats

注意事项

As @mgaddamentioned in the comments below, git checkout -ptries to apply the whole difference between a commit and the current workspace.

正如@mgadda在下面的评论中提到的,git checkout -p尝试应用提交和当前工作区之间的全部差异。

In the case of a git stash, if the stash you're trying to apply was done against a different commit, then git checkout -p stash@{n}will try to apply interactively all the differences between the commit stash@{n}and the commit of the current workspace, including all their parent commits that are different.

在 git stash 的情况下,如果您尝试应用的 stash 是针对不同的提交完成的,那么git checkout -p stash@{n}将尝试以交互方式应用stash@{n}当前工作区的提交和提交之间的所有差异,包括它们的所有父提交是不同的

For example, if you're trying to apply a stash that was saved "many commits ago" into the current workspace, git checkout -p stash@{n}will try to apply not only the changes in the stash proper, but will also try to revertall changes that happened between the commit on which the stash is based and the current commit.

例如,如果您尝试将在“多次提交前”保存的存储应用到当前工作区,git checkout -p stash@{n}则不仅会尝试应用存储中的更改,还会尝试还原在两次提交之间发生的所有更改存储所基于的提交和当前提交。

Conversely, if you're trying to apply a stash "from the future", i.e. into a branch that is a number of commits from before the commit on which the stash is based, then git checkout -p stash@{n}will try to also apply all the other changes that happened between the current commit and the commit from the future, besides the changes from the stash itself.

相反,如果您尝试应用“来自未来”的存储,即应用到一个分支,该分支是存储所基于的提交之前的多次提交,那么git checkout -p stash@{n}将尝试也应用发生的所有其他更改在当前提交和未来提交之间,除了存储本身的更改。

(In case you're wondering, git checkout -p stash@{n}a stash from a parallel branch will try to revert all changes between the current commit and the original branching point andalso apply all changes between the branching point and the other branch, besides the change in the stash).

(如果您想知道,git checkout -p stash@{n}并行分支中的存储将尝试恢复当前提交和原始分支点之间的所有更改,并且除了存储中的更改之外还会应用分支点和另一个分支之间的所有更改) .

Workarounds

解决方法

There are a few workarounds, none of them are perfect for every situation:

有一些解决方法,但没有一种方法适用于所有情况:

    1. Be really careful with the patches you accept when you do git checkout -p stash@{n}
    1. Do a git stash pop, then git stashagain before doing git checkout -p .... But if you wanted to do a partial apply of your stash to avoid conflicts, this won't really help. In that case, see solution 4 below.
    1. If you have a graphical diff tool supported by git (like meld), you can use git difftooland "apply left" only the changes you're interested in:

      • git difftool -d stash@{n}to compare a whole stash and all its files

      • git difftool stash@{n} -- path/to/fileto compare a single file

    1. (Based on @andrew's answer)On a detached head, go back to the "parent" commit of the stash you're interested in, apply the stash, re-stash interactively only the parts you're interested in, go back and reapply the smaller stash.
    1. 在接受补丁时要非常小心 git checkout -p stash@{n}
    1. 做一个git stash pop,然后git stash再做git checkout -p ...。但是,如果您想部分应用您的存储以避免冲突,这将无济于事。在这种情况下,请参阅下面的解决方案 4。
    1. 如果您有 git 支持的图形差异工具(如meld),您可以仅使用git difftool和“左应用”您感兴趣的更改:

      • git difftool -d stash@{n}比较整个存储及其所有文件

      • git difftool stash@{n} -- path/to/file比较单个文件

    1. (基于@andrew 的回答)在一个分离的头上,返回到您感兴趣的存储的“父”提交,应用存储,仅交互地重新存储您感兴趣的部分,返回并重新应用较小的藏匿处。

Step by step:

一步步:

git checkout stash@{n}^  # notice the "^". 

# Now you're in a detached head in the parent commit of the stash.
# It can be applied cleanly:
git stash apply stash@{n}

# Now save only the diffs you're interested in:
git stash -p

# remove the rest of the old stash
git checkout -- .  # be careful or you could remove unrelated changes

# go back to the branch where you want to apply the smaller stash
git checkout <my previous branch>

# apply the smaller stash
git stash pop

回答by user829755

What I often do (in git bash) is

我经常做的(在 git bash 中)是

git stash show -p 'stash@{0}' >tmp.patch

Then I edit the file and remove the parts I don't want. Finally I say

然后我编辑文件并删除我不想要的部分。最后我说

<tmp.patch git apply

or

或者

<tmp.patch patch -p1

It doesn't work for binary files, though, but neither does the accepted answer (using checkout -p) for them.

但是,它不适用于二进制文件,但接受的答案(使用 checkout -p)也不适用于它们。

回答by Andrew

I don't think there's a way to apply changes by hunks (or even by file). You will have to apply the stash, then stash the changes you don't want interactively (with git stash save -p). If you're worried about conflicts, you can stash any uncommitted changes first, apply your stash, stash any conflicting hunks and then apply the other stash.

我认为没有办法通过大块头(甚至通过文件)应用更改。您必须应用存储,然后以交互方式存储您不想要的更改(使用git stash save -p)。如果您担心冲突,您可以先存储任何未提交的更改,应用您的存储,存储任何冲突的大块,然后应用其他存储。

回答by ruvim

One possible way is to reset the index and then use interactive add

一种可能的方法是重置索引,然后使用交互式添加

# 0. ensure there are no uncommitted changes
git status

# 1. apply a changeset as is
git stash apply stash@{n}
# ... fix or discard conflicts if any

# 2. reset the index 
git reset

# 3. interactively add the required chunks (except new files)
git add -p

# 4. stash all other changes
git stash save --keep-index "comment"
# 4. or just discards all other changes in the working tree
git checkout-index -f -a

# 5. commit
git commit -m "comment"

Another way is to use interactive resetin place of interactive add.

另一种方法是使用交互式重置代替交互式添加。

# 0. ensure the working tree does not have unstaged changes
git status

# 1. apply a changeset as is
git stash apply stash@{n}
# ... fix or discard conflicts if any

# 2. interactively exclude the unneeded chunks from the index 
git reset -p

# 3. stash all other changes
git stash save --keep-index "comment"
# 3. or just discards all other changes in the working tree
git checkout-index -f -a

# 4. commit
git commit -m "comment"