Git 工作流程及分支策略

2021-04-12 11:08:44 +08:00
 liuxing

本文首发于 刘星的个人网站

Git 是目前世界上最先进的分布式版本控制系统。它使我们更方便的跟踪,管理和组织代码。也帮助了我们更好的与其他开发者进行协作开发。但是没有规矩不成方圆。协作开发必须有一个规范来约束各个贡献者的行为。这个规范就是 Git 工作流程(Git Workflow),也为我们规范各个分支管理策略等行为。

Git 工作流程是有关如何使用 Git 以高效协作开发的规则或策略建议,下文这些常见工作流程只是作为指导参考,这些工作流不是一成不变的,我们应该根据自己的项目选择或制定合适自己的工作流。

集中式工作流

首先我们来介绍最简单粗暴的集中式工作流,如果你用过SVN,那么你可以无痛切换到 Git 集中式工作流。该工作流只用到 master 这一个主分支来维护我们的代码,这也是该工作流的主要工作方式。

工作流程示例

1 、首先 clone 远程仓库到本地

git clone ssh://user@host/path/to/repo.git

2 、然后在本地的 master 分支做出修改完成开发后,创建一个提交

git status # 查看本地仓库的修改状态
git add # 暂存文件
git commit # 提交文件

3 、然后推送到远程仓库

git push origin master

4 、 如果此时本地仓库与远程仓库有了分歧,Git 将拒绝操作并报错。这时我们就应该先 pull 远程仓库的修改到本地仓库后再解决重新推送

git pull --rebase origin master

5 、如果有冲突,Git 会在合并有冲突的提交处暂停 rebase 过程,并报出错误信息,我们在解决掉冲突后可以使用一下命令将更改加入暂存区后继续只能执行 rebase:

git add <some-file>
git rebase --continue

如果遇到一个搞不定的冲突,这可以使用一下命令来终止 rebase

git rebase --abort

主要遵循原则

优点

缺点

如果在稍大的团队中使用前面的集中式工作流,那么可能会在解决冲突中浪费很多时间。在实际开发中我们基本上都是都 功能驱动式开发,基于功能需求,创建相应的分支进行开发,完成开发合并到主分支后再被删除掉。接下来我们介绍的三个工作流:GitHub Flow,Git Flow 及 Gitlab Flow 都是基于不同的分支管理策略运作的。

GitHub Flow 工作流

GitHub Flow 是一个轻量级的基于分支的工作流程。它由 GitHub 在 2011 年创建。分支是 Git 中的核心概念,并且 GitHub 工作流程中的一切都以此为基础。

最重要的的一点就是:**main / master分支中的任何内容始终都是可部署的**。其他分支(功能分支)创建用于新功能和错误修复的工作,并且在工作完成并经过检查后,这些分支将合并回到主分支中后删除。这些分支名应该是具有描述性的如 refactor-authentication, user-content-cache-key, make-retina-avatars

工作流程示例

1 、首先 clone 远程仓库到本地

git clone ssh://user@host/path/to/repo.git

2 、根据要实现的功能创建一个新的分支,分支名应该具有描述性,如实现鉴权功能:feature-auth

git checkout -b feature-auth

3 、然后将新工作提交到该分支下,并定期将工作推送到远程仓库

# 创建一个 commit
git status # 查看本地仓库的修改状态
git add # 暂存文件
git commit # 提交文件

# 将分支推送到远程仓库
git push --set-upstream origin feature-auth

4 、当你需要帮助或者反馈,或是你觉得你已经完成该功能的工作准备合进主分支的时候创建 pull request

5 、当你的这部分工作在 pull request 中,被 review 以及 approved 后,则可以合并到主分支。

git checkout master
git pull
git pull origin feature-auth
git push

6 、合并到主分支后,应立即对其进行部署

主要遵循原则

  1. master 分支中的任何内容都是可部署的
  2. 要进行新的工作,需要从主分支master 创建出一个分支,并给出描述性的名称(如:new-oauth2-scopes
  3. 本地的修改提交到该分支,并定期将你的工作推送到服务器上的同一命名分支
  4. 当你需要反馈或帮助时,或者你认为分支已准备好进行合并时,请打开一个Pull Request
  5. 在其他人 Review 并 Approved 该功能后,你可以将其合并到 master
  6. 合并并推送到后主分支master,你可以并且应该立即进行部署

优点

缺点

Git Flow 工作流

基于功能分支的工作流是一中相当灵活的方式。但是问题也是有时候过于灵活。对于大型团队,常常需要给不同分支分配一个更具体的角色。Git Flow 工作流是管理功能开发、预发布和维护的常用模式。

Git Flow 是最早诞生并且相当流行的工作流程。它由 Vincent Driessen 于 2010 年创建。Git Flow 工作流定义了一个围绕项目发布的严格分支模型。虽然比 GitHub Flow 的功能分支工作流复杂一点,但提供了用于一个健壮的用于管理大型项目的框架。

Git Flow 工作流没有用超出功能分支工作流的概念和命令,Git Flow 为不同的分支分配一个很明确的角色,并定义分支之间如何和什么时候进行交互。

工作流程示例

假设你已经创建好了中央仓库,并且已将其 clone 到本地

1 、首先我们来从主分支创建一个开发分支 develop, 并推送到服务器

git branch develop
git push -u origin develop

以后这个分支将会包含了项目的全部历史,而 master 分支将只包含了部分历史

2 、接下来我们开始开发新功能,基于 develop 分支创建新的功能分支

git checkout -b some-feature develop

并在自己的功能分支上进行开发、创建提交:

git status # 查看本地仓库的修改状态
git add # 暂存文件
git commit # 提交文件

3 、当你在你的分支上完成工作,准备好进行合并时,请打开一个 Pull Request,用于合并到develop分支。如果你的团队没使用 Pull Request 则可以直接合并到本地的 develop 分支然后推送到中央仓库。

git pull origin develop
git checkout develop

git merge --no-ff some-feature
git push
# 删除本地分支
git branch -d some-feature

并且在功能分支合并后应该立即删除

4 、当我们的 develop 分支进行到需要发布时,需要从develop分支创建一个新的发布分支,命名为release-*release/*。这一步也确定了发布的版本号:

git checkout -b release-0.1.0 develop

这个分支是一个预发布的版本,只做 bug 修复、文档生成等面向发布的任务。新功能不再添加到这个分支上

5 、经过一系列测试确认没有问题,准备好了对外发布后,我们需要将发布分支合并到 master 分支,并打下 tag

git checkout master
git merge --no-ff release-0.1
git push
git tag -a 0.1 -m "release 0.1 publish" master
git push --tags

6 、同时我们还需要将这个发布分支合并回去 master 分支

git checkout develop
git merge --no-ff release-0.1.0
git push

最后我们还需要删除掉这个发布分支 release-0.1.0

7 、如果我们的线上版本出现问题时,就需要创建一个维护分支,用于快速给产品打补丁。这个维护分支需要从master分支上创建,提交修改以解决问题,然后再直接合并回master分支:

git checkout -b hotfix-auth master

修复完成后将其合并到 master 分支

git checkout master
git merge --no-ff hotfix-auth
git push

同时打下新的 tag

git tag -a 0.1.1 -m "release 0.1.1 publish" master
git push --tags

同样也需要将修复分支合并到 develop 分支

git checkout develop
git merge --no-ff hotfix-auth
git push

最后删除掉这个热修复分支

git branch -d hotfix-auth

主要遵循原则

它基于两个长期的主要分支:

其次在开发中还有三种短期分支

优点

缺点

Gitlab Flow 工作流

GitLab Flow 是通过创建工作流 GitLab在 2014 年。它将功能驱动的开发和功能分支以及问题跟踪结合在一起。它是 Git Flow 与 GithubFflow 的综合。它吸取了两者的优点,既有适应不同开发环境的弹性,又有单一主分支的简单和便利。GitLab Flow 和 GitHub Flow 之间的最大区别是 GitLab Flow 中的环境分支支持(例如stagingproduction),

GitLab Flow 的最大原则叫做"上游优先"( upsteam first ),即只存在一个主分支master,它是所有其他分支的"上游"。只有上游分支采纳的代码变化,才能应用到其他分支。

GitLab Flow 分成两种情形来应付不同的开发流程

持续发布

对于持续发布的项目,它建议在master分支以外,再建立不同的环境分支,每个环境都会有对应的分支。比如,开发环境的分支是master,预发环境的分支是pre-production,生产环境的分支是production

如果生产环境(production)发生错误,则要建一个新分支修改完后合并到最上游的开发分支(master)此时就是 Upstream first),且经过测试,再继续往 pre-production branch,要经过测试没有问题了才能够再往下合并到生产环境。

版本发布

对于"版本发布"的项目,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable2-4-stable等等。

再出现 bug 后,根据对应的 release branch 创建一个修复分支,修复工作万和城呢个后,一样要按着上游优选的原则,先合并到 master 分支,经过测试才能到才能够合并到 release 分支,并且此时要更新小版本号。

工作流程示例

和之前一样。首先 clone 项目到本地

1 、当我们要实现新功能或是修复 bug 时。从 master 检出新的分支如:feature-auth

git checkout -b feature-auth

2 、然后在该分支下进行工作,完成后创建提交

git status # 查看本地仓库的修改状态
git add # 暂存文件
git commit # 提交文件

推送代码到远程仓库,

git push origin feature-auth

3 、代码推送到仓库后,自定运行 GitLab CI

4 、当我们开发完成准备合并进 master 时,在 GitLab 上创建一个 Merge Request

5 、项目管理者进行代码审查,通过后,合并到master

6 、运行第二次 GitLab CI

7 、通过相应的测试后,将master分支合并到stable,如果是新版本则创建一个新的stable分支

8 、为stable打上 tag,并进行发布

主要遵循原则

  1. 使用功能分支,不直接提交( commit )到 master 分支
  2. 测试所有的提交,而不仅仅只在 master 分支上
  3. 在所有的提交上,运行所有的测试(如果你的测试时间长于 5 分钟则让它们并行)
  4. 在合并到 master 之前执行代码审查,而不是事后审查
  5. 部署是自动的,并基于分支或标签( tag )
  6. 标签( tag )是由用户设置的,而不是由 CI 创建
  7. 发布( release )是基于标签( tag )的
  8. 永远不对已推送的提交( pushed commits )进行变基( rebase )
  9. 每个人都从 master 分支开始工作,目标也是 master 分支
  10. 在 master 分支中修正错误,其次再到发布分支
  11. 提交信息( commit message )应体现意图

优点

缺点

总结及建议

没有一个万能的适合所有项目的 Git 工作流程及分支策略,无论最终选择哪种策略,你都可以通过进一步的修改来优化它。就像前文所说的,Git 工作流程对我们提升团队生产力非常重要,在制定我们的工作流程时,应该尽量符合我们的项目具体业务需求及开发环境。但是也有如下几点小建议:

参考链接

本文完

欢迎可以关注我的公众号,一起玩耍。有技术干货也有扯淡乱谈

左手代码右手砖,抛砖引玉

2890 次点击
所在节点    git
6 条回复
labulaka521
2021-04-12 15:17:07 +08:00
我想把这玩意染成绿色
liuxing
2021-04-12 16:19:14 +08:00
@labulaka521 哈哈哈 家有儿女
pocketz
2021-04-12 21:52:36 +08:00
赞,最近刚准备从 SVN 往 git 转
MarioLuo
2021-04-13 01:24:16 +08:00
github flow 下 codereview 是先提 PR, 还是先测试?
1.先测试后再提 PR, 这时候审查代码会变更有风险
2.先 PR 审查, 但是未测试的代码不小心被合并了的风险
liuxing
2021-04-13 09:21:42 +08:00
vishun
2023-01-05 14:24:43 +08:00
@MarioLuo #4 感觉这个就是 github flow 的缺点,它没有集成测试的分支,具体要在哪里切入测试环节很多人都有疑问,而 gitlab flow 多了分支可以解决集成测试的问题,但这里又有个问题:
文章中描述如果生产环境发生错误,也要遵循 Upstream first 原则,从 master 开始修复,但此时 master 如果又更新了怎么办?而更新的部分并不一定想和这个错误一起发布到生产环境,这里难道只能用 cherry pick 来修复吗?
这么一反而感觉 git flow 是最全的没有明显缺陷的方式呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/770008

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX