如何防止分叉 git 回购分歧
How to prevent forked git repo from diverging
以下一系列 git 命令导致回购分歧。我做错了什么?
- 来自 GitLab 的 Fork 项目
call the parent project 'upstream'
- 从分叉项目克隆回购
- 在分支 master 中进行本地编辑
- 提交本地编辑,推送到分支仓库
- 上游回购有来自其他开发者的提交
- 从上游仓库获取最新的提交
git pull --rebase upstream master
- 将来自上游的最新提交合并到本地
分叉回购
git push origin master
- 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
也就是说,上游有新的提交 d
和 e
,并且您已经进行了新的提交 f
、g
和 h
现在,你 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'
其中 f
和 f'
不是同一个提交 - 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'
?两者都没有保留对方的历史。
您可以合并这些,但那是错误的,因为您在 f
和 f'
、g
和 g'
等中进行了等效更改
你可以做到
git push -f
这将从 fork 中丢弃 f
、g
和 h
,并使其看起来像 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 因为它只是添加额外的提交。
不过,如果您打算向上游发出拉取请求,最好不要合并他们的更改,让他们拉取并处理合并。
以下一系列 git 命令导致回购分歧。我做错了什么?
- 来自 GitLab 的 Fork 项目
call the parent project 'upstream'
- 从分叉项目克隆回购
- 在分支 master 中进行本地编辑
- 提交本地编辑,推送到分支仓库
- 上游回购有来自其他开发者的提交
- 从上游仓库获取最新的提交
git pull --rebase upstream master
- 将来自上游的最新提交合并到本地
分叉回购
git push origin master
- 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
也就是说,上游有新的提交 d
和 e
,并且您已经进行了新的提交 f
、g
和 h
现在,你 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'
其中 f
和 f'
不是同一个提交 - 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'
?两者都没有保留对方的历史。
您可以合并这些,但那是错误的,因为您在 f
和 f'
、g
和 g'
等中进行了等效更改
你可以做到
git push -f
这将从 fork 中丢弃 f
、g
和 h
,并使其看起来像 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 因为它只是添加额外的提交。
不过,如果您打算向上游发出拉取请求,最好不要合并他们的更改,让他们拉取并处理合并。