GitHub中的Forking和Branching对比

346

我想了解在github项目中分叉(fork)和创建分支(branch)的优缺点。

分叉可以让我的版本与原始项目更加独立,因为我不必被添加到原始项目的协作者列表中。由于我们正在内部开发一个项目,所以将人员添加为协作者没有问题。但是,我们想了解是否分叉项目会使合并更改回主要项目变得更加困难。换句话说,我想知道分支是否使得保持两个项目同步更容易。换言之,当我创建分支时,在我的主要项目版本和主要项目之间合并和推送更改是否更容易?

4个回答

336

您不能总是创建一个分支或拉取现有分支并将其推回,因为您未在该特定项目中注册为协作者。

分叉不过是在 GitHub 服务器端进行的克隆:

  • 无法直接推回
  • 添加了分叉队列功能以管理合并请求

通过以下方式使 fork 与原始项目保持同步:

  • 将原始项目作为远程添加
  • 定期从原始项目中获取
  • 将当前开发重新基于您从该提取中更新的感兴趣的分支之上。

重新基于可以确保您的更改是简单明了的(无需处理合并冲突),这使得当您希望原始项目的维护者将您的补丁包含在他的项目中时,您的拉取请求更加容易。

目标是真正允许协作,即使直接参与并非总是可能的。


这意味着你在 GitHub 上进行克隆,现在有了两个“中央”存储库(“中央”指“可由多个协作者查看”)。 如果您可以直接将他们添加为一个项目的协作者,则无需使用 fork 来管理另一个项目。

fork on GitHub

合并体验基本相同,但多了一层间接性(先在分支上推送,然后请求拉取,有可能原仓库的更新会导致你的快进合并不再是快进)。这意味着正确的工作流程是 git pull --rebase upstream(将你的工作重新基于上游的新提交),然后 git push --force origin,以便以这样的方式重写历史记录,使你自己的提交始终位于原始(上游)仓库的提交之上。参见:Git fork is git clone?Pull new updates from original Github repository into forked Github repository

3
我们正在内部开发一个项目,添加成员作为协作者没有问题。但我们想知道分叉(Fork)一个项目是否会使将更改合并回主要项目变得更加困难。 - reprogrammer
8
如果您可以添加协作者,则不需要使用Forking。他们可以在本地进行变基,然后合并到目标分支,然后直接推送到一个中央存储库,而不是必须管理两个中央存储库(原始存储库和Fork)。当涉及到Fork时,变基的操作大致相同,但会增加一些额外的间接性。再说一遍:这里不需要。我已经更新了我的答案。 - VonC
18
老实说,即使您不必这样做,拥有一个仅供高级开发人员、团队领导或其他“可信任”人员编写的神圣代码存储库总是一个好主意。所有其他团队成员应该在其分支(~沙盒)中工作,并以拉取请求的形式贡献其更改。由于分布式版本控制系统使其成为可能,我们将其作为“最佳实践”进行了适应,并成功地将其应用在最小的项目中... - intland
2
@intland,那么您更倾向于采用 http://stackoverflow.com/users/6309/vonc?tab=responses 中描述的“集成管理工作流”吗?由于我曾经在一家大公司引入Git,因此我倾向于首先采用集中式工作流程(对每个人来说更为熟悉),然后再转向“集成管理器”工作流程。 - VonC
21
我们应该把“叉子”称作“小树枝”,因为它们是从树枝上断掉的,并且用来开始一棵全新的树。这只是我的个人意见 - 我喜欢这种树木习语。 - Eric
显示剩余2条评论

99

以下是高级别的区别:

分叉

优点

  • 保持用户间分支的独立性
  • 减少主要存储库中的混乱
  • 您的团队流程反映了外部贡献者的流程

缺点

  • 更难查看所有活动(或不活动)的分支
  • 在分支上进行协作更加复杂(分叉所有者需要将人添加为协作者)
  • 您需要理解Git中多个远程的概念
    • 需要额外的心理记账
    • 对于不太熟悉Git的人来说,这会使工作流程更加困难

分支

优点

  • 将项目中所有正在进行的工作集中在一个地方
  • 所有协作者都可以推送到同一个分支上进行协作
  • 只有一个Git远程需要处理

缺点

  • 废弃的分支可能更容易堆积
  • 您的团队贡献流程与外部贡献者的流程不匹配
  • 您需要将团队成员添加为贡献者,然后才能进行分支操作

1
“外部贡献者流程”是什么意思? - Kars Barendrecht
1
@KarsBarendrecht 已更新为使用术语“外部贡献者”。指那些在存储库上没有“写入”权限的人。 - Aidan Feldman
如果您有很多被遗弃的分支,建议建立一个明确放弃分支的流程。例如,在分支上进行最后一次提交,并注释为“BRANCH ABANDONED”。这有助于在需要合并时找到被遗漏的分支。 - Forbin

49

这与Git的一般工作流程有关。您不太可能直接推送到主项目的存储库。我不确定GitHub项目的存储库是否支持基于分支的访问控制,因为您不希望授予任何人例如对主分支进行推送的权限。

一般的模式如下:

  • 派生原始项目的存储库,以拥有自己的GitHub副本,随后您将被允许推送更改。
  • 将您的GitHub存储库克隆到本地计算机上
  • 可选地,在您的本地存储库中将原始存储库添加为另一个远程存储库。然后,您就可以直接获取该存储库中发布的更改。
  • 在本地进行修改和提交。
  • 将更改推送到您的GitHub存储库(通常您没有直接操作项目存储库的写入权限)。
  • 联系项目维护者,请他们获取您的更改并审核/合并,如果您和他们都同意,则让他们推送回项目存储库。

如果没有这样做,公共项目很少允许任何人直接推送自己的提交。


1
@RecoJohnson,嗯...我在我的回答中没有使用“pull”这个词(但是在Git术语中,“pull”实际上是“fetch”+“merge”)。你认为哪种“push”的用法是错误的? - Bruno
3
您作为贡献者将更改推送到您在GitHub上的分支;项目维护者从您的分支中拉取您的贡献。 - mljrg
1
我认为,在使用git的开发团队中,你不太可能被分配到合作者这一假设在开源世界中更为真实,而在许多有着明确定义的开发团队的组织中则不然。我认为这是一个重要的区别,但人们并没有足够地意识到它,这也许就是像GitLab这样的公司蓬勃发展的原因,因为他们理解企业的需求和对控制的需求。 - code4cause

15

分支(Branch)创建一个新的分支,基于现有的工作版本库

使用分支的最佳场景: 当需要创建一个逻辑上独立的项目时,可以将其与原始项目永久分离。

更加具体地说:在开源项目中,仓库的所有者决定谁可以向仓库推送。然而,开源的理念是每个人都可以为项目做出贡献。

这个问题通过 Fork 解决:开发人员想要修改开源项目中的内容时,不会直接克隆官方仓库。相反,他们会分叉(Fork)仓库以创建一份副本。完成工作后,他们会发起合并请求,以便仓库的所有者审查更改,并决定是否将其合并到他的项目中。

从根本上讲,Fork 与功能分支类似,但它不是创建分支,而是创建仓库的分支,而不是进行合并请求,你需要创建一个拉取请求。

以下链接提供了一个清晰解释:

https://blog.gitprime.com/the-definitive-guide-to-forks-and-branches-in-git/

https://buddy.works/blog/5-types-of-git-workflows

http://www.continuousagile.com/unblock/branching.html


1
这个答案中的“最佳使用”语句似乎忽略了许多问题,这些问题阻止了分支对于像开源项目这样的事物的工作,以及分支在现实世界中的使用方式。非常普遍的情况是看到分支与拉取请求一起使用,以允许人们协作一个项目,这些人不都有权限直接修改给定的存储库。 - StriplingWarrior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接