我想知道如何压缩所有合并分支的提交:
feature | c3 - merge_master - c6
/ / \
master | c1 - c2 - c5 ------------- merge_feature - c7
我的目标是拥有这个
master | c1 - c2 - c5 - squash_c3_c6 - c7
我发现git rebase c6 c5 --onto c6
允许我重播c3
和c6
以c3'
和c6'
,但我总是c3
和{ {1}}在我的历史中。
我必须在脚本中执行此操作以处理大型存储库(超过6k分支!)因此我无法使用c6
有什么想法吗?
答案 0 :(得分:0)
你不能(完全)得到你想要的东西,但你得到的东西可能会很好。
在Git中,“壁球”意味着“复制”。更具体地说,“squash merge”使用Git的合并机制,执行合并操作(单词 merge 作为动词),但随后进行普通提交。例如,假设你有这个:
C3--C6 <-- feature
/
C1
\
C2--C5 <-- master
(请注意,master
或feature
之类的分支名称实际上只指向一个提交,即分支的提示提交;而某些提交位于两个分支,例如C1
)。然后运行git checkout master && git merge --squash feature
:
C1
作为分支共享提交的最后位置; C5
作为当前分支的提示master
; C6
作为feature
。这些是合并过程的输入(“合并”作为动词)。然后Git会:
C1
与C5
:这是“我们改变了什么”; C1
与C6
:这是“他们改变了什么”。--squash
自动打开--no-commit
,因此Git会在此时停止,而不进行提交,但会构建预加载的提交消息。
您现在可以运行git commit
,它会进行普通提交(不是合并提交 - 它使用单词 merge 作为形容词,描述类型承诺)。那个普通的提交就是你想要的:
C3--C6 <-- feature
/
C1
\
C2--C5--C7_which_is_3_plus_6 <-- master (HEAD)
此时,分支名称feature
唯一明智的做法是删除它,放弃原始提交C3
和C6
(最终,或者甚至很快,垃圾收集:删除分支也删除分支的保护它们的reflog。)
C7
的日志消息是您想要的,但根据您配置Git的方式,您可以将其默认为组合来自C3
和C6
的现有日志消息(将merge.log
设置为true
或至少为2的数字,或使用--log
。
请注意新的提交C7
,其中包含原始C3
和C6
中的内容(减去C5
已复制的内容)。据推测,这可以使feature
完全像这样删除。
不幸的是,那不是你拥有的。您已经可以从feature
的提示处获得合并提交,并提供您绘制的图表:
C3--C4--C6 <-- feature
/ /
C1--C2--C5 <-- master
feature
和master
的合并基础现在不是提交C1
,而是提交C2
。这是因为当我们从master
开始向后工作时,我们会找到提交C5
,然后是C2
,然后是C1
;当我们从feature
开始向后工作时,我们会找到C6
,然后是C4
,然后同时找到C3
和C2
;然后是C1
。
这意味着C2
,而不是C1
,是对两个分支上的两个分支提示的“最近”提交。然后在git merge --squash
上使用master
:
C2
vs C5
:我们改变了什么; C2
vs C6
:他们改变了什么; --no-commit
然后,您可以进行新的提交C7
:
C3--C4--C6 <-- feature
/ /
C1--C2--C5----C7 <-- master
同样,feature
唯一明智的做法就是删除它。结果将是序列...--C1--C2--C5--C7
。 这是与之前相同的提交序列,更重要的是,与C7
关联的树(源内容)应该与您的树相同只要C4
本身不是evil merge且C4
不撤消C6
的一部分,d就会获得C4
。
原因是C4
包含C3
的更改,显然C6
包含C6
的更改。这意味着当Git运行git diff C2 C6
时,它会看到C3
和C6
中的更改:这些是merge-as-a-verb进程的两个输入之一。因此,新C7
包含您想要的所有更改。
根据--log
和merge.log
设置,不的内容是自动填充日志消息。但您可以按照自己喜欢的方式编辑C7
的日志消息,包括查找早期提交,例如C1
并使用git log --pretty=short --no-merges <hash>..feature
。
答案 1 :(得分:0)
我认为你要找的是git filter-brabch
,它会从合并提交中删除第二个父母。
像(未经测试!)
git filter-branch --parent-filter 'read pkey pvalue rest && echo "$pkey $pvalue"' branch_first_commit..branch
(sed或awk可能会更快但是我害怕引用时会出错。它可能在第一次提交时失败)
说明:较旧的历史记录可能存在冲突,因此无法自动重播分支历史记录。但“被压缩的合并”只是与被移除的第二个父母的合并。而且你已经有了合并,所以你只需要删除父母。
答案 2 :(得分:0)
所以我玩git filter-branch --parent-filter
它允许我将所有合并的分支提交压平在我的主人身上,很有用,但是松散正确的提交顺序=&gt; C1--C3--C2--C4--C5
。结果很好,但历史变得不一致,我期待像C1--C2--C3--C4--C5
这样的东西,即便如此,它仍然是压制C3和C4。
@torek感谢您的解释,我更好地理解C2和C3是C4的同等祖先,没有原点概念,如“从功能分支提交”或“从合并分支提交”。并且有“合并提交”但只是提交合并。
我发现有一种方法来编写rebase interactive mode的脚本,就像我可以通过rebase interactive实现我想要的东西,我将编写脚本。
我会随时通知你