关于StackOverflow上的“flattening merge”的问题很少,答案通常是“git rebase”。这些答案虽然错过了一个关键点 - 提交顺序。
假设有一个分支A,提交6月1日和8月1日,分支B提交7月1日(UPDATE 恢复下面描述的用例:分支完全独立,没有共同的祖先,例如来自2个不同的存储库)。将B合并为A时,将有以下历史记录(每个git日志):
Merged branch 'B'
Aug 1
Jul 1
Jun 1
现在,我正在寻找的是获得相同结果的方法,但是没有合并提交(因此在该顺序中具有基础线性历史,是的,这意味着重新提交提交的父级)。 git rebase在这里没有用,就像它一样,你会得到以下历史:
Jul 1
Aug 1
Jun 1
要么
Aug 1
Jun 1
Jul 1
换句话说,git rebase总是将一个分支堆叠在另一个分支之上,而我正在寻找解决方案,它将按作者的提交日期排序提交。
显然,对于简单的情况,可以通过使用git rebase -i手动后处理git rebase来实现所需的安排,但这对大型历史来说并不实用,所以我一直在寻找自动命令/脚本。
用例?如果A和B代表同一个项目的不同部分恰好在不同的回购中,并且时间已经通过将它们合并在一起来纠正,那么很自然地希望线性历史以实际的开发顺序展开。
经过一番思考后,我想出了怎么做 如何以非交互方式运行git rebase --interactive? ,它还为这个问题提供了完全脚本化的解决方案。
1。 将来自不同存储库的2个分支放入一个存储库(git remote add + git fetch)
2。 Rebase(非交互式)一个分支在另一个分支之上(顺序很重要,考虑首先提交您想要拥有的分支作为第一次提交的合并分支)。
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
4。 跑: GIT_SEQUENCE_EDITOR=./rebase-reoder-by-date git rebase -i <initial commit>
免责声明:所有这些操作都应该发生在原始存储库的副本上,审查/验证/测试组合分支,以确保它符合您的预期并包含您的期望,保持备份方便。
将合并后的单独开发留在合并之前有什么问题?如果他们是分开的,那么他们是分开的。
有许多方法可以按时间顺序查看历史记录,而不会在您尝试时破坏历史记录。你有没有尝试过 git log --pretty --date-order
?
[请参阅我的另一个答案,了解完全自动化我将此作为导致最终解决方案的路径的一个例子,以防有人将面临类似的不那么明显的解决任务。
好吧,这不是问题的真正答案(完全脚本化,自动化的解决方案),但思考和示例如何(基于交互式rebase)处理可以自动化。
嗯,首先,为了最终的解决方案 git filter-branch --parent-filter
看起来确实需要什么。除了我的git-fu不允许我用它编写1代,2代或3行代码,并且编写独立脚本以解析所有修订版的方法并不比rebase -i更酷,更省力。
因此,如果提交的作者日期可见,则可以有效地使用rebase -i。我的第一个想法是暂时修改提交消息以使用作者日期开始 git filter-branch --msg-filter
,运行rebase -i,然后重新发送消息。
第二个想法是:为什么要麻烦,更好地修改rebase -i使用的rebase提交列表。那么,过程将是:
- 像往常一样,将不同回购的分支A和B带入一个回购。
- Rebase(非交互式)一个分支在另一个分支上。考虑应该对哪个分支进行重新分配,以使初始提交权利(不能用rebase轻松重写)。
- 开始
git rebase -i
- 在另一个控制台中,转到$ REPO / .git / rebase-merge /
- 跑:
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"; }' git-rebase-todo > git-rebase-todo.new; mv git-rebase-todo.new git-rebase-todo
- 这似乎是重新排序提交的正确位置/方式:
sort -k3 git-rebase-todo >git-rebase-todo.new; mv git-rebase-todo.new git-rebase-todo
- 切换到原始控制台并在编辑器中重新加载git-rebase-todo文件,然后退出编辑器。
瞧!实际上,这可以完全编写脚本 git rebase -i
我提交了,可以在“非交互”模式下工作 如何以非交互方式运行git rebase --interactive? 为了那个原因。
实际上,如果我理解正确,你可以轻松实现这一目标 混帐十字绣回购。