关于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
现在,我正在寻找的是获得相同结果的方法,但是没有合并提交(因此在该顺序中具有基础线性历史,是的,这意味着重新提交承诺)。 git rebase在这里没有用,就像它一样,你会得到以下历史:
Jul 1
Aug 1
Jun 1
或
Aug 1
Jun 1
Jul 1
换句话说,git rebase总是将一个分支堆叠在另一个分支之上,而我正在寻找解决方案,它将按作者的提交日期排序提交。
显然,对于简单的情况,可以通过使用git rebase -i手动后处理git rebase来实现所需的安排,但这对于大型历史记录来说并不实用,所以我一直在寻找自动命令/脚本。
USECASE?如果A和B代表同一个项目的不同部分碰巧在不同的回购中,并且时间已经通过将它们合并在一起来纠正,那么很自然地希望线性历史以实际的发展顺序展开。
答案 0 :(得分:11)
经过一番思考后,我想出了如何做How do I run git rebase --interactive in non-interactive manner?,这也为这个问题提供了完全脚本化的解决方案。
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>
免责声明:所有这些操作都应该发生在原始存储库的副本上,审查/验证/测试组合分支,以确保它符合您的预期并包含您的期望,并保持备份方便。
答案 1 :(得分:2)
将单独的开发分开,直到它们合并为止,会出现什么问题?如果它们是分开的,那么它们是分开的。
有许多方法可以按时间顺序查看历史记录,而不会在您尝试时破解历史记录。你试过git log --pretty --date-order
吗?
答案 2 :(得分:1)
[请参阅我的另一个完全自动化解决方案的答案。我将此作为导致最终解决方案的路径的一个例子,以防有人将面临类似的不那么明显的解决任务。]
好的,这不是问题的真正答案(完全脚本化的自动化解决方案),但思考和示例如何(基于交互式基于rebase)处理可以自动化。
嗯,首先,最终的解决方案git filter-branch --parent-filter
看起来正是需要的。除了我的git-fu不允许我用它编写1代,2代或3行代码,并且编写独立脚本以解析所有修订版的方法并不比rebase -i更酷,更省力。< / p>
因此,如果提交的作者日期可见,则可以有效地使用rebase -i。我的第一个想法是使用git filter-branch --msg-filter
临时修改提交消息以使用作者日期开始,运行rebase -i,然后重新发送消息。
第二个想法是:为什么要麻烦,更好地修改rebase -i使用的rebase提交列表。所以,过程将是:
git rebase -i
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
git show --format='%ai' -s " $2 "
瞧!实际上,如果sort -k3 git-rebase-todo >git-rebase-todo.new; mv git-rebase-todo.new git-rebase-todo
可以在“非交互式”模式下工作,这可以完全编写脚本,我提交了How do I run git rebase --interactive in non-interactive manner?。
答案 3 :(得分:0)
实际上,如果我理解正确,您可以使用git-stitch-repo轻松实现这一目标。