Git存储和编辑补丁

13
我非常喜欢git add -pgit stash,但偶尔会遇到以下问题,该问题可以通过以下命令序列重现:
  • git add -p my_file:接下来我手动编辑一个 hunk (使用 e),因为git建议的拆分不适合我。
  • git stash --keep-index:然后我进行一些测试,如果测试通过,我就不提交
  • git stash pop:现在出现了问题:my_file文件 被视为冲突,而且git已经完全搞乱了我的编辑的hunk,所以我必须编辑文件,删除无用的合并标记,并运行git add my_file,接着是git reset HEAD

我很困惑,因为这只发生在手动编辑 hunk 的情况下。我不明白这应该有何区别。


要重现这个问题:

  • touch newfile
  • git add newfile
  • git commit -m'newfile'
  • 在文件中添加两行
  • git add -p newfile
  • 编辑 hunk (e),在 hunk 中删除其中一行,然后退出 git add (q)
  • git stash --keep-index
  • git stash pop

现在,文件newfile处于未合并状态。请注意,再次强调,如果没有手动编辑任何 hunk,则上述命令不会有任何问题。

顺带一提,文件的前一个状态位于第三阶段(git show :3:newfile),之前托管的版本位于第二阶段(git show :2:newfile)。因此,通过某些 git 黑魔法,我可以将第二阶段放入此索引中,并将第三阶段放入工作库中......但我不知道如何做到这一点,所以我只能手动处理。 :-(


我尝试了几次,但是我无法在git版本1.7.2.3中重现您的问题。您使用的是哪个版本? - Sven Marnach
我在Mac OS X上使用的是1.7.3.1版本。 - Olivier Verdier
1
我尝试了不同的随机编辑方式在 git add -p 中,对我来说一直都很好用。顺便说一下,我使用的是Linux系统。听起来像是一个bug -- 我建议你在git邮件列表上询问,他们会非常乐意帮助解决问题。 - Sven Marnach
根据邮件列表,这不是一个错误,而是预期的行为。虽然我不明白为什么... - Olivier Verdier
2
Frank的回答解决了这个问题。 - axk
3个回答

9
创建并测试包含部分工作树更改的索引,包括手动编辑的块,执行以下操作:
git add --patch <files>

git stash --keep-index

<test the indexed changes>

git reset --hard

git stash pop --index

此时没有冲突,存储库、索引和工作目录处于紧接着git stash之前的状态。您现在可以git commit这些已索引的更改。

当然,这样做相当奇怪且不太直观,我真的很想知道是否有更简单的方法。


1
+1,这个可行。我自己也想到了同样的解决方案,但错过了--index开关。考虑到它会存储索引和未暂存的更改,因此避免工作副本中已暂存更改和已存储更改之间的合并冲突,必须先从工作副本中删除它们(即进行硬重置),这是一种逻辑上的做法。 - axk

4
我在git邮件列表中提出了问题。我描述的是预期行为。这不是一个bug。 :-(
以下是我得到的答案:
如果您没有手动编辑hunk,则每个hunk将处于状态HEAD或状态A,并将HEAD和A之间的差异应用于此类文件,将是无操作(hunk已应用)或成功应用。
对我来说,这是git add --patch的严重限制,我不明白这种行为对任何人有什么用处,但我会学会适应它。

1
看起来问题在于当你运行 "git stash --keep-index" 命令时,它会将已经暂存和未暂存的更改全部存储,唯一的区别是它会保留已经暂存的更改到工作副本。当你尝试应用这个存储时,已经暂存的更改既存在于工作副本中,也存在于存储中,导致了冲突。对于那些没有修改的代码块,Git 会记住哪些代码块存在于工作副本中,哪些不存在,并且不会将已经存在于工作副本中的代码块再次应用,从而避免合并冲突。但是,对于编辑过的代码块,只有应用部分更改是无法解决问题的。 - axk

2

git stash --keep-index 保留了你的索引,但它仍将索引内容作为存储的一部分添加。

尝试使用 git stash save -p -- 这种方法保存起来可能有点繁琐,但是它可能会达到你想要的效果。


这如何解释git仅在手动编辑块时才认为存在冲突? - Olivier Verdier
因为当你使用 git stash pop 时,你的索引不匹配。 - Scott
@Scott:抱歉,我不理解你的回答... :-/ 为什么只有在手动编辑了一部分内容后才会出现冲突呢? - Olivier Verdier
@Olivier - 请参考Sven上面的评论:值得在git列表上询问,看看你是否发现了一个bug。 - bstpierre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接