如何防止分叉 git 回购分歧

How to prevent forked git repo from diverging

以下一系列 git 命令导致回购分歧。我做错了什么?

  1. 来自 GitLab 的 Fork 项目

    call the parent project 'upstream'

  2. 从分叉项目克隆回购
  3. 在分支 master 中进行本地编辑
  4. 提交本地编辑,推送到分支仓库
  5. 上游回购有来自其他开发者的提交
  6. 从上游仓库获取最新的提交

    git pull --rebase upstream master

  7. 将来自上游的最新提交合并到本地 分叉回购

    git push origin master

  8. git 表示我的分支分别有 x 次提交和 y 次提交。要求我做一个 git pull 最终会弄乱历史。

正确的做法是什么?

让我们解决这个问题。

有 3 个存储库:您的本地克隆、上游、您的分支(本地克隆的来源)

在第 2 步之后,它们看起来像这样:

上游

o---o---o
a   b   c

分叉

o---o---o
a   b   c

本地

o---o---o
a   b   c

第 5 步之后,回购协议看起来像这样:

上游

o---o---o---o---o
a   b   c   d   e

分叉

o---o---o---o---o---o
a   b   c   f   g   h

本地

o---o---o---o---o---o
a   b   c   f   g   h

也就是说,上游有新的提交 de,并且您已经进行了新的提交 fgh

现在,你 git pull --rebase upstream master

存储库现在看起来像这样:

上游

o---o---o---o---o
a   b   c   d   e

分叉

o---o---o---o---o---o
a   b   c   f   g   h

本地

o---o---o---o---o---o---o---o
a   b   c   d   e   f'  g'  h'

其中 ff' 不是同一个提交 - f' 应该等同于 f,但它有不同的父项。

你可以在这里看到,local 现在和 fork 有不同的历史;推动它不仅仅是添加新提交的情况。两者都认为 c 之后有不同的提交,并且两个分支不收敛;如果你添加了所有的提交,你最终会得到这个图表:

        ,-----------o---o---o
        |           f   g   h
o---o---o---o---o---o---o---o
a   b   c   d   e   f'  g'  h'

当前的 HEAD 是什么? h 还是 h'?两者都没有保留对方的历史。

您可以合并这些,但那是错误的,因为您在 ff'gg' 等中进行了等效更改

你可以做到

git push -f

这将从 fork 中丢弃 fgh,并使其看起来像 local(你仍然有 f'g'h'),如果没有其他人从 fork[=125= 克隆,这可能很好]

在第 6 步,你可以不做变基,而是做

git pull upstream master

这将导致合并,因此回购协议将如下所示:

上游

o---o---o---o---o
a   b   c   d   e

分叉

o---o---o---o---o---o
a   b   c   f   g   h

本地

        ,---o---o---o---,
        |   f   g   h   |
o---o---o---o---o-------o
a   b   c   d   e       m

其中 m 是合并提交。然后可以通过简单地将其推送到 fork 因为它只是添加额外的提交。

不过,如果您打算向上游发出拉取请求,最好不要合并他们的更改,让他们拉取并处理合并。