【问题标题】:'git stash apply' with Interactive Mode带有交互模式的“git stash apply”
【发布时间】:2015-03-27 13:27:56
【问题描述】:

我有一系列文件到存储区 (stash{0}),我想 git apply 只是这些文件的一些部分/大块(通常称为 交互模式)。

有可能吗?

我已经看到可以执行一个

git stash save -p 'Stash name'

但是好像做不到

git stash apply -p 'Stash name'

你知道实现它的方法吗?

【问题讨论】:

标签: git git-stash chunks interactive-mode


【解决方案1】:

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

【讨论】:

  • 是的,我主要是问因为我想避免冲突。目的是从(比方说)branch_A 获得一些更改,并能够将它们放在branch_B 上,从而能够直接避免这两个分支可能发生的冲突。您的解决方案有效,但正是我想避免的“复杂”方式;-P
  • 相反的方法,只是 git stash save 以交互方式让我 想要 的帅哥,然后在所需的分支上恢复它,而不是 git stash apply 以交互方式我 确实想要,似乎是最好的方法。
【解决方案2】:

有可能吗?

是的!

git checkout -p stash@{0}

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

如果您不确定要应用哪个 n,请使用 git stash listgit show -p stash@{n}

当您知道不再需要该存储时,不要忘记git stash drop stash@{n},因为git checkout 显然不会为您丢弃存储。

为什么有效?

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

确实,它们存储在.git/refs/stash 中,每个存储散列一行。

注意事项

正如下面 cmets 中提到的@mgaddagit checkout -p 尝试应用提交和当前工作空间之间的全部差异。

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

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

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

(如果您想知道,git checkout -p stash@{n} 来自并行分支的存储将尝试还原当前提交和原始分支点之间的所有更改并且也会应用分支之间的所有更改point 和另一个分支,除了 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. (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

【讨论】:

  • 这里有一个警告需要提一下:因为存储只是提交,这意味着它们也有父提交,这些父提交不能保证与您要交互式应用更改的父提交相同。经验法则:如果您从其他提交而不是当前签出的提交中隐藏,则此技术不会达到您的预期。解决方法:从您的存储应用整个更改集(使用 git stash pop),然后再次存储(git stash)。现在你可以根据需要 git checkout -p 了。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

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

    <tmp.patch git apply
    

    <tmp.patch patch -p1
    

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

    【讨论】:

    • 不错的选择,谢谢! –我认为无论如何,就像在接受的答案中一样,有必要在创建补丁之前检查存储所指的父提交;否则它最终还会包括来自中间提交的大量更改(在“当前签出的提交”和“存储的父提交”之间),如 mgadda's comment 中所述。
    • 不,tmp.patch 的内容不取决于您在创建它时检查的内容。只有 git apply 会受到影响,如果受影响的代码行同时发生变化,它会报告合并冲突
    • 抱歉,我错过了“我编辑文件并删除了我不想要的部分”部分。恕我直言,这也是令人讨厌的部分,因为手动编辑容易出错。
    猜你喜欢
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 2015-03-11
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多