真的压扁了git merge

pfa*_*con 11 git merge rebase git-rewrite-history

关于StackOverflow上的"flattening merge"的问题很少,答案通常是"git rebase".这些答案虽然错过了一个关键点 - 提交顺序.

假设有一个分支A,其中包含6月1日和8月1日的提交,而分支B具有7月1日的提交(更新以恢复下面描述的用例:分支是完全独立的,没有共同的祖先,例如来自2个不同的存储库).将B合并到A中时,会有以下历史记录(每个git日志):

Merged branch 'B'
Aug 1
Jul 1
Jun 1
Run Code Online (Sandbox Code Playgroud)

现在,我正在寻找的是获得相同结果的方法,但是没有合并提交(因此具有基础线性历史的顺序,是的,这意味着重新提交提交).git rebase在这里没有用,就像它一样,你会得到以下历史:

Jul 1
Aug 1
Jun 1
Run Code Online (Sandbox Code Playgroud)

要么

Aug 1
Jun 1
Jul 1
Run Code Online (Sandbox Code Playgroud)

换句话说,git rebase总是将一个分支堆叠在另一个分支之上,而我正在寻找解决方案,它将按作者的提交日期排序提交.

显然,对于简单的情况,可以通过使用git rebase -i手动后处理git rebase来实现所需的安排,但这对大型历史来说并不实用,所以我一直在寻找自动命令/脚本.

用例?如果A和B代表同一个项目的不同部分碰巧在不同的回购中,并且时间已经通过将它们合并在一起来纠正,那么很自然地希望线性历史以实际的开发顺序展开.

pfa*_*con 12

经过一番思考后,我想出了如何做到如何以非交互方式运行git rebase --interactive?,它还为这个问题提供了完全脚本化的解决方案.

1.将来自不同存储库的2个分支放入一个存储库(git remote add + git fetch)

2.重新(非交互式)一个分支在另一个分支之上(顺序很重要,考虑首先提交你想要拥有的分支作为第一次提交的合并分支).

3.准备以下脚本(rebase-reoder-by-date):

#!/bin/sh
awk '
/^pick/ {
            printf "%s %s ", $1, $2;
            system("echo -n `git show --format='%ai' -s " $2 "`");
            for (i = 3; i <= NF; i++) printf " %s", $i; printf "\n";
        }
' $1 | sort -k3 > $1.tmp
mv $1.tmp $1
Run Code Online (Sandbox Code Playgroud)

4.运行:GIT_SEQUENCE_EDITOR=./rebase-reoder-by-date git rebase -i <initial commit>

免责声明:所有这些操作都应该发生在原始存储库的副本上,审查/验证/测试组合分支,以确保它符合您的预期并包含您的期望,保持备份方便.