git - 更快到达 `git rebase --preserve-merges` 的方法

标签 git merge rebase

我通过创建一系列功能分支来使用 git,并在完成后使用 git merge --no-ff 将它们 merge 到 master。这会创建空的 merge 提交,可用于识别先前功能分支的起点和终点。

为了处理多个并发分支,甚至嵌套分支,我使用了 rebase。我从不 merge 回来,我总是根据最新的提交重新调整我的分支,测试并最终在一切完成后与 --no-ff merge 。对于嵌套分支,我执行相同的操作:多个分支按顺序 merge 到主分支上,主分支本身最终 merge 到 master 中。

为了保留有关与嵌套分支 merge 的信息,我经常使用git rebase --preserve-merges。这正是我想要的,并且我的工作流程没有任何问题。

我对 git 的主要问题是 git rebase --preserve-merges 非常慢(有时每次提交大约需要 2 秒)。看完What exactly does git's "rebase --preserve-merges" do (and why?)我意识到 git 必须执行大量工作来保留 merge ,因为 git 必须处理任意图。

我想知道的是:由于我的工作流程几乎产生了相当于线性历史的图表,有没有办法以更快的速度执行 git rebase --preserve-merge 等效操作方式,鉴于我保证历史的“线性”只有空的 merge 提交?我不介意使用脚本或奇怪的命令,只要最终结果是正确的。

     A-B-C
    /     \   
(1)--------D-- master
    \
     \---F-----I-- feature
      \ / \   /
       E   G-H

     A-B-C   E   G-H
    /     \ / \ /   \
(2)--------D---F-----I-feature
         master

tl; dr: 如何将 (1) 转换为 (2) 知道基础历史是线性的,因此 git rebase --preserve-merges 不必做那么多工作并且可以做到这一点快吗?

最佳答案

可能可以通过将bash脚本重写为更聪明的东西来加快速度(例如,在Python中,运行git rev-list --parents 使用一组适当的修订分隔符,并在开始复制操作之前收集所有父级信息),但从根本上来说这很困难。正如其他链接中的答案顺便指出的那样,git rebase -p 也并不完全保留 merge ,而是重新创建它们。在完全一般的情况下——我知道你会忽略这种情况,而倾向于更有限的特殊情况;我只是为了完整性才提到这一点 - git rebase -p 在应用了特殊选项或处理的 merge 时完全失败(--no-commit 与手动修改 merge 以生成“邪恶 merge ”,或使用 -X rename-threshold-X ours 或类似的方式运行 merge ),因为特殊情况信息实际上仅存储在由此产生的树。 rebase 代码甚至不寻找它(这将花费更长的时间:它必须首先重现原始 merge ,只是为了看看无选项 merge 是否会重新创建原始结果)。

除此之外,这些选项的速度(或速度不够)取决于您的存储库及其文件的大小,以及您使用的是 Windows(非常慢)还是 Unixish 系统(更快)。我没有理由知道 Windows 运行脚本会如此缓慢,但显然确实如此,因为 Git 人员不断用 C 重写东西,以使它们在 Windows 上执行得可接受,因为脚本太慢了。

因此,如果您在 Windows 上执行此操作,加快速度的一种方法是停止使用 Windows。 :-) (您可以在 rebase 本身的持续时间内执行此操作,使用 git push 和 git fetch 在 Windows 和 Linux 之间进行协调。)

关于git - 更快到达 `git rebase --preserve-merges` 的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46517373/

相关文章:

git - 从 repo 中删除跟踪的忽略文件,但不在本地

python - 如何合并列表中具有相等值的字典和不相等的连接值并将其他字段保留在字典中?

python - 如何在python中合并csv数据

git - 如何检查 git rebase 发生了什么变化?

Git repo : internal and open source external branches

Git rebase 和 Vim 编辑器

Git - 将文件标记为新文件而不是移动/复制

git - 删除旧的、已推送的 git commit 中对文件的更改?

linux - 将本地存储库制作为公共(public)存储库?

Android list 合并 : removing LAUNCHER intent-filter doesn't take effect