真正压平 git 合并 [英] Really flatten a git merge

查看:21
本文介绍了真正压平 git 合并的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 StackOverflow 上很少有关于扁平化合并"的问题,答案通常是git rebase".这些答案虽然忽略了一个关键点 - 提交顺序.

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

合并分支'B'8月1日7月1日6 月 1 日

现在,我正在寻找的是获得相同结果的方法,但没有合并提交(因此具有按该顺序排列的潜在线性历史记录,是的,这意味着重新提交提交).git rebase 在这里没有帮助,因为使用它,您将获得以下历史记录:

7 月 1 日8月1日6 月 1 日

8 月 1 日6 月 1 日7月1日

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

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

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

解决方案

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

1. 将来自不同仓库的 2 个分支合并到一个仓库(git remote add + git fetch)

2. 将一个分支(以非交互方式)重新设置在另一个之上(顺序很重要,请考虑您希望将哪个分支的第一次提交作为合并分支的第一次提交).>

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

#!/bin/shawk '/^挑选/{printf "%s %s ", $1, $2;system("echo -n `git show --format='%ai' -s " $2 "`");for (i = 3; i <= NF; i++) printf " %s", $i;printf "
";}' $1 |排序 -k3 >$1.tmpmv $1.tmp $1

4. 运行:GIT_SEQUENCE_EDITOR=./rebase-reoder-by-date git rebase -i

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

There're few question about "flattening merge" on StackOverflow, with an answer usually being "git rebase". These answers though miss one crucial point - order of commits.

Suppose there's a branch A with commits of Jun 1 and Aug 1, and branch B with commit of Jul 1 (UPDATE to reinstate the usecase described below: branches are fully independent and don't have common ancestry, for example coming from 2 different repositories). When merging B into A, there will be following history (per git log):

Merged branch 'B'
Aug 1
Jul 1
Jun 1

Now, what I'm looking for is the way to get the same result, but without merge commit (and thus with underlying linear history in that order, and yes, that means re-parenting commits). git rebase doesn't help here, as with it, you will get following histories:

Jul 1
Aug 1
Jun 1

or

Aug 1
Jun 1
Jul 1

In other words, git rebase always stacks one branch on top of another, while I'm looking for solution which will intersperse commits sorted by author's commit date.

Apparently, for simple cases, needed arrangement can be achieved by manually postprocessing git rebase with git rebase -i, but that's not practical for large histories, so I'd be looking for automated command/script.

Usecase? If A and B represent different parts of the same project which happened to be in different repos and time has come to correct that by merging them together, then it's natural to want the linear history unfolding in the actual order of development.

解决方案

After some thinking, I figured out how to do How do I run git rebase --interactive in non-interactive manner? , which also provides completely scripted solution for this question.

1. Bring 2 branches from different repositories into one repository (git remote add + git fetch)

2. Rebase (non-interactively) one branch on top of another (order matters, consider first commit of which branch you'd like to have as first commit of consolidated branch).

3. Prepare following script (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 "
";
        }
' $1 | sort -k3 > $1.tmp
mv $1.tmp $1

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

Disclaimer: all these operations should happen on copies of original repositories, review/validate/test combined branch to make sure it is what you expected and contains what you expect, keep backups handy.

这篇关于真正压平 git 合并的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆