如何使git am/git apply像patch命令一样“模糊”工作?

44

我一直在使用 git-format-patch 和 git-am 将一个仓库的更改应用到另一个仓库中。文件结构相同,但是我要应用到的仓库有一些更改,导致大多数补丁失败了几个 hunks。但是大多数补丁 hunks 的行号都有一点模糊。

据我所知,git-am apply 非常严格,因此会直接拒绝所有这些补丁。

因此,我的工作流程变成了:

$ git am ../the-patch.patch
# Fails because the patch doesn't apply cleanly
$ patch -p1 < ../the-patch.patch
# Applies most of the hunks, leaves .rej files for the ones that conflict
# Fix the conflicting hunks manually
$ git am --continue

如果我不需要运行命令行补丁并且可以将其作为am命令的一部分完成,那就太好了。

使用--reject标志运行似乎会在文件中创建一个.rej文件,其中包含所有块(如果有任何冲突),这不是我想要的。

使用--3way标志运行失败。

fatal: sha1 information is lacking or useless (the-file.java).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.

我猜是因为此基础更改集不在我正在合并的存储库中。

是否有任何方法使git-am apply像原始补丁命令一样进行模糊匹配,并仅创建包含失败块的.rej文件?


看起来很有用和有趣。你能提供一个sscce的例子来一起工作吗?我猜一个包含第一次提交文件和补丁以及第二次提交期望结果(应用hunks和.rej文件)的repo就足够调查了。 - albfan
@albfan 抱歉,这个问题太久了,我甚至都难以记得原来的上下文,更别说重现了。 - EdC
6个回答

5
你可以执行以下操作:
git am /path/to/some.patch
patch -p1 < /path/to/some.patch
git add .
git am --continue

那将应用补丁并保留提交信息等。

1
非常好!所以,在这里,patch命令是你的朋友。在使用git add .时要小心 - 你可能会添加.orig文件(最好添加相应的文件而不是.)。 - kumar

2
如何看待以下问题:
git_apply-fuzzy() {
   if ! git am "$@"; then
      local patch="$(git rev-parse --show-toplevel)/.git/rebase-apply/patch"
      if [ -e "$patch" ] && patch --dry-run -p1 < "$patch"; then
          if patch -p1 < "$patch"; then
              sed -n -e '/^+++ b\//{s///;p}' "$patch" | xargs git add &&
              git am --continue &&
              return 0 ||
              patch -p1 -R < "$patch"
          fi
      fi
      git am --abort
      return 1
   fi
}
git_apply-fuzzy mypatch.patch

它会尝试使用“git am”命令,如果失败则尝试使用补丁(patch),在任何异常情况下都会进行还原操作。请保留HTML标签。

在你的sed表达式中,;是不必要的。由于你正在处理补丁,我建议使用除了/之外的另一个分隔符。最后,你可以用一个命令匹配行并替换表达式。最后你可以只使用s:^+++ b/::p - undefined

1
如果我理解正确,您正在尝试将一个代码库的代码合并到另一个代码库中,但在某些代码部分上失败了。然后您手动修复它,并且从现在开始,您希望它能够无误地合并。
在这种情况下,您应该使用git rerere命令。
在采用相对较长寿命的主题分支的工作流程中,开发人员有时需要一遍又一遍地解决相同的冲突,直到主题分支完成(要么合并到“发布”分支,要么发送并被上游接受)。此命令通过记录冲突的自动合并结果和相应的手动解决结果以及将先前记录的手动解决方案应用于其相应的自动合并结果来协助开发人员进行此过程。
git config --global rerere.enabled true

2
我不明白这如何使git am更加积极地模糊偏移量。 - Nick Desaulniers

1
根据@Nick Desaulniers上面链接的帖子,似乎使用-3选项来执行git apply/am可以在某种程度上解决问题。例如,这是我使用一个未能通过git apply的补丁所得到的输出:$ git apply < patch_file.patch error: patch failed: file_being_patched.txt:489 error: file_being_patched.txt: patch does not apply $ git apply -3 < patch_file.patch error: patch failed: file_being_patched.txt:489 Falling back to three-way merge... Applied patch to 'file_being_patched.txt' cleanly.
很遗憾它仍然会显示错误(对于脚本来说更难解析输出),而且它不像patch那样指出模糊级别,因为模糊级别通常是判断补丁命令是否可能出错的好指标。

0

这是一个功能请求的雏形。要确认这一点,请加入Git邮件列表(git@vger.kernel.org)并阅读一段时间,以了解文化氛围。同时,按照上述建议准备好前后文档,澄清自己的想法。

当您感觉准备好了,就在列表中介绍自己,并简洁地解释您的想法。务必回答您的提案是否可以通过其他方式充分实现的问题。如果得到鼓舞人心的话,那么请跟进更详细的文档。有了来自您提案的反馈意见,您可以决定是否继续提交功能请求错误,或者您可能会发现自己有能力创建补丁以供考虑。


谢谢您的建议,我已经发送了邮件列表。可以在这里跟踪该线程。 - Nick Desaulniers
由于我无法再编辑我的评论(5分钟限制),这里是该主题的链接。 - Nick Desaulniers

0

有一个--recount参数,但只适用于git-apply命令,因此理论上的顺序应该是:

git mailsplit ...   
git mailinfo ...
git apply --recount ...
git add ...
git commit ...

3
它是做什么的? - Andreas Haferburg

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