使用交互模式'git stash apply'

问题描述 投票:28回答:3

我有一系列文件藏匿(stash{0}),我想git apply只是这些文件的一些部分/帅气(通常称为交互模式)。

可能吗?

我已经看到有可能执行一个

git stash save -p 'Stash name'

但似乎不可能做到

git stash apply -p 'Stash name'

你知道实现它的方法吗?

git git-stash chunks interactive-mode
3个回答
42
投票

可能吗?

Yes it is!

git checkout -p stash@{0}

在哪里可以用0中的stash@{0}替换你想要应用的藏匿的索引。

使用git stash listgit show -p stash@{n},如果不确定哪个n是你要申请的藏匿处。

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

Why does it work?

关键是要意识到,stashes本质上是referencescommits就像标签和分支。

实际上,它们存储在.git/refs/stash中,每行存储一行。

Caveats

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

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

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

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

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

Workarounds

有一些解决方法,它们都不适用于所有情况:

  • 当你做git checkout -p stash@{n}时,要非常小心你接受的补丁
  • 在做git stash pop之前再做一次git stash,然后git checkout -p ...。但是如果你想部分应用你的藏匿来避免冲突,这将无济于事。在这种情况下,见下面的解决方案4。
  • 如果您有git支持的图形差异工具(如meld),您可以使用git difftool并“仅向左应用”您感兴趣的更改: git difftool -d stash@{n}比较整个存储及其所有文件 git difftool stash@{n} -- path/to/file比较单个文件
  • (Based on @andrew's answer)在一个独立的头上,回到你感兴趣的存储的“父”提交,应用存储,只交互地重新存储你感兴趣的部分,返回并重新应用较小的存储。

一步步:

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

2
投票

我认为没有办法通过帅哥(甚至是文件)来应用变化。您将不得不应用存储,然后以交互方式存储您不想要的更改(使用git stash save -p)。如果您担心冲突,可以先存储任何未提交的更改,应用您的存储,存储任何冲突的数据,然后应用其他存储。


2
投票

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

# 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"

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

# 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"
© www.soinside.com 2019 - 2024. All rights reserved.