我有一个非常复杂的合并要做。问题的一部分在于我让太多时间过去了,因此纳入我的分支的变化数量是巨大的。
为了简化操作,我选择git merge origin/master~20
,然后git merge origin/master~17
,git merge origin/master~15
等,这样我就能以零散的方式解决冲突问题,而不必采取措施一下子。
问题是这会导致我希望摆脱的日志历史的污染。合并所有这些提交的最佳方法是什么,同时仍然保持结果提交指向我的分支和主服务器?
我通常使用git reset --soft
压缩但不会留下对主分支的引用。我还尝试了git rebase -i --preserve-merges
但我收到了"Refusing to squash a merge"
错误消息。
我该怎么办?
答案 0 :(得分:2)
让我用这种方式描述你的情况:你有你想要的合并结果 - 源树 - 但不是你想要的历史导致这个结果。< / p>
作为VonC has put it elsewhere,您自己尝试了,git reset --soft
通常 答案。您执行软重置,然后进行新的提交。如果此时只能进行 merge 提交,那么它仍然是答案。
如果没有git rerere
,有三种简单的方法可以做到这一点。一种是作弊,其中一种方式是记录作弊&#34;因此可能是正确的方法。 (我喜欢的方法是中间的,因为它很短而且很甜,但显然是作弊,所以有一天它可能会停止工作。)
请注意,此处的命令序列假定您位于存储库的顶层(特别是下面的git rm
和git checkout
步骤,请参阅.
表示&#34;所有内容& #34)。我还使用$startpoint
进行您想要进行合并的提交,并$other
引用另一个分支名称或提交ID(您想要git merge
的那个)。
保存最终结果的ID(我们想要树,但标准工具最简单的方法是引用提交,这也可以正常工作):
$ git tag temp-save-result
(或使用剪切和粘贴或reflog来保存它;为了简单起见,我在这里展示了一个标签)。
复位。这可能是--hard
,而不是--soft
:
$ git reset --hard $startpoint
运行合并,但会因冲突而失败。忽略冲突并删除整个索引和工作树。我们不想要冲突的合并,或者到目前为止的任何临时结果,因为我们有正确的结果在别处。
$ git merge $other
$ git rm -r .
(如果你有一些自定义合并工具留下粪便,你可能也希望在这里清除工作树中的那些,虽然它们不会影响任何重要的东西:它们只是混乱你的工作树。)
提取步骤1中保存的工作树,并提交结果:
$ git checkout temp-save-result -- .
$ git commit
此提交结束合并,其树来自您在步骤1中保存的树。您现在可以删除标记:
$ git tag -d temp-save-result
当git commit
进行新提交时,如果.git/MERGE_HEAD
存在,则进行合并提交。 MERGE_HEAD
文件包含第二次提交的ID,即正在合并的其他或远程或--theirs
。
因此,我们像往常一样进行软重置,然后添加合并ID,然后提交。 (注意:我最近没有尝试过,Git可能也想要.git/MERGE_MSG
。准备好调整作弊,或者继续进行方法3.)
$ git reset --soft $startpoint
$ git rev-parse $other > .git/MERGE_HEAD
$ git commit
第一个命令是我们通常的git reset --soft
步骤,第二个命令是Git说我们正在解决冲突的合并(并且索引全部已解决,因此我们必须完成该步骤) ,git commit
现在提交合并。
生成实际提交对象的命令 - git commit
毫无疑问只是一个在末尾附近运行它的shell脚本git commit-tree
。它要求:
-m
或-F
)并将新的提交对象写入存储库,并打印出对象的哈希ID。
我们已经树了!由于它是当前提交,因此其ID为HEAD^{tree}
(使用gitrevisions
syntax)。我们也有两个父ID。我们所需要的只是信息:
$ tmp=$(git commit-tree -p $startpoint -p $other -m 'merge msg' HEAD^{tree})
一旦我们有了提交ID,我们只需要git reset --hard
我们当前的分支指向它:
$ git reset --hard $tmp
(当然,你可以在第二个命令中使用$(...)
而不是$tmp
将这两个组合成一个大命令,尽管这假设你的git commit-tree
命令可以工作:它&#39为了个人舒适,可能最好做两个步骤。如果您更喜欢,可以通过剪切和粘贴哈希ID来省略$tmp
变量和相应的shell $(...)
语法。并且,你可以输入一个俗气的临时提交消息,然后在重置后用git commit --amend
编辑它:--amend
选项也适用于合并提交。)