Git现在已经是程序员的标配了,几乎所有的项目都在用Git做版本控制。但是很多人对Git的理解还停留在commit、push、pull这几个命令上,对于团队协作中的Git工作流、分支策略、代码评审等等了解不深,导致团队协作的时候经常出问题,比如代码冲突、版本混乱、线上出bug等等。
其实Git不只是一个版本控制工具,更是一个团队协作的工具,用好Git工作流能大大提升团队的协作效率和代码质量。我用Git也有好几年了,从单人开发到团队协作都经历过,踩了不少坑也总结了不少经验,今天就来分享一下Git工作流的最佳实践。
一、为什么需要Git工作流
很多人觉得Git不就是commit、push、pull吗,搞那么多花里胡哨的工作流有什么用?其实当项目只有一个人的时候,确实不需要什么工作流,想怎么提交就怎么提交,反正只有自己一个人。但是当团队人数多了,项目复杂了,没有一个规范的工作流就会出很多问题。
比如没有分支策略,所有人都直接往master分支提交代码,那master分支就会很不稳定,经常有人提交了有bug的代码导致整个项目跑不起来,其他人拉代码下来就没法工作了。而且要发布版本的时候也很麻烦,不知道哪些代码是可以发布的,哪些是还没写完的。
再比如没有代码评审,每个人提交的代码质量参差不齐,有人写的代码有bug有安全隐患,也没人发现,直接就合并到主分支了,最后线上出了问题才发现,这时候修复成本就很高了。
还有提交信息不规范,有人提交信息就写"更新"、"修改"、"fix",根本不知道这次提交改了什么,以后出了问题想回溯都找不到对应的提交,非常痛苦。
所以一个规范的Git工作流是非常有必要的,它能让团队协作更顺畅,代码质量更有保障,出了问题也更容易追溯和修复。
二、常见的Git工作流
现在比较流行的Git工作流有这么几种,各有优缺点,适合不同的团队和项目。
1. Git Flow
Git Flow是比较经典的一种工作流,它定义了五种分支:master、develop、feature、release、hotfix。master分支存正式发布的版本,develop分支是开发主分支,feature分支用来开发新功能,release分支用来准备发布版本,hotfix分支用来修复线上的紧急bug。
这种工作流的优点是规范清晰,每个分支的职责很明确,适合版本发布周期比较固定的项目,比如桌面软件、手机App这种有明确版本号的项目。缺点是流程比较复杂,分支多,维护成本高,对于持续发布的Web项目来说可能有点笨重。
2. GitHub Flow
GitHub Flow比Git Flow简单很多,它只有一个长期分支master,其他都是临时的feature分支。开发新功能的时候从master拉一个feature分支,开发完之后提Pull Request,经过代码评审之后合并回master,然后就可以部署了。
这种工作流的优点是简单灵活,适合持续集成持续部署的Web项目,现在很多互联网公司都用这种或者类似的工作流。缺点是对自动化测试和部署的要求比较高,因为master分支随时都要能部署,所以必须有完善的测试和部署流程。
3. GitLab Flow
GitLab Flow是在GitHub Flow的基础上做了一些改进,增加了环境分支,比如pre-production、production,代码先合并到master,然后合并到预发布环境测试,没问题再合并到生产环境发布。它结合了Git Flow和GitHub Flow的优点,既简单灵活又能很好地控制发布流程。
还有一些团队会根据自己的情况定制工作流,没有哪种工作流是最好的,只有最适合自己团队的。选择工作流的时候要考虑团队规模、项目类型、发布周期、自动化程度等等因素,不要盲目跟风,别人用得好的不一定适合你。
我们团队现在用的是类似GitHub Flow的工作流,因为我们是Web项目,需要频繁发布,这种简单灵活的工作流比较适合我们。下面就以我们团队的工作流为例,分享一些最佳实践。
三、分支策略最佳实践
不管用哪种工作流,分支策略都是核心,好的分支策略能让开发更顺畅,减少冲突和混乱。
1. 主分支保持稳定可部署
master分支(或者叫main分支)必须保持稳定,随时都能部署,不能把没写完的、有bug的代码合并到master。所有的开发都应该在feature分支上进行,开发完测试通过了才能合并回master。这是最基本也是最重要的一条原则。
2. feature分支要小而短
每个feature分支只做一件事,不要一个分支里改很多东西,比如既加新功能又重构代码还修bug,这样代码评审的时候很难看,出了问题也不好回溯。一个feature分支的生命周期也不要太长,最好几天之内就能合并,分支存在时间越长,和master的差异就越大,合并的时候冲突就越多。如果功能很大,可以拆分成多个小的feature分支,逐步合并。
3. 分支命名要规范
分支名字要能看出来这个分支是做什么的,建议用类型加描述的方式,比如feature/user-login、fix/login-error、refactor/user-service。类型一般有feature(新功能)、fix(修复bug)、refactor(重构)、docs(文档)、style(格式)、test(测试)等等。规范的命名能让大家一眼就知道每个分支是做什么的,管理起来也方便。
4. 及时同步master的代码
在feature分支开发的过程中,要经常把master的代码合并过来,或者rebase到最新的master,不要等开发完了要合并的时候才同步,那时候可能已经差了很多代码,冲突会很严重。建议每天开始工作之前先同步一下master的代码,有冲突尽早解决,不要攒到最后。
5. 删除已经合并的分支
feature分支合并到master之后就没用了,要及时删掉,不要留着。远程分支和本地分支都要删,不然分支列表会越来越长,找都找不到。很多Git平台都有自动删除已合并分支的功能,可以打开。
四、提交信息最佳实践
提交信息(commit message)非常重要,它是代码的历史记录,以后出了问题要回溯,或者想知道某段代码为什么这么写,都要靠提交信息。但是很多人不重视提交信息,随便写几个字就提交了,这是非常不好的习惯。
好的提交信息应该遵循一定的格式,现在比较流行的是Conventional Commits规范,格式是:
<type>(<scope>): <subject>
<body>
<footer>type是提交类型,和分支类型类似,有feat(新功能)、fix(修复bug)、docs(文档)、style(格式)、refactor(重构)、perf(性能优化)、test(测试)、chore(构建/工具)等等。
scope是影响范围,可选,比如user、order、payment这些模块名。
subject是简短描述,不超过50个字,用祈使句,不要加句号。
body是详细描述,可选,说明这次提交的原因、思路、修改了什么等等。
footer是备注,可选,比如关联的issue号、破坏性变更说明等等。
举个例子:
feat(user): 添加用户登录功能
- 支持手机号密码登录
- 支持短信验证码登录
- 添加登录状态校验
Closes #123这样的提交信息清晰明了,一看就知道这次提交做了什么,以后回溯的时候也很方便。而且规范的提交信息还能用来自动生成changelog,发布版本的时候自动生成更新日志,非常方便。
还有一点要注意,一个commit只做一件事,不要把很多不相关的修改放在一个commit里。比如你改了登录的bug,顺便又改了首页的样式,还加了个新功能,这三个应该分成三个commit,不要放在一起。这样以后想回滚其中一个修改的时候就很方便,不会把其他修改也回滚了。
五、代码评审最佳实践
代码评审(Code Review)是保证代码质量的重要环节,也是团队成员互相学习的好机会。但是很多团队的代码评审流于形式,或者根本不做,这是很不好的。
1. 所有代码合并前都要评审
不管是新功能还是修bug,不管是新人写的还是老员工写的,所有代码合并到master之前都要经过至少一个人的评审。不要觉得自己写的代码没问题就不用评审了,自己写的代码自己很难发现问题,别人看一眼可能就发现了。而且代码评审也能让团队成员互相了解彼此的代码,不会出现只有一个人懂某块代码的情况。
2. 评审要及时
提了Pull Request之后要及时评审,不要放个两三天都没人看,这样会阻塞开发进度。建议团队约定一个评审的响应时间,比如4小时内必须有响应,紧急的bug修复要立即评审。评审的时候也要认真看,不要随便点个通过就完事了,那还不如不评审。
3. 评审要关注重点
代码评审不是要你逐行检查语法错误(这些应该交给lint和测试),而是要关注更重要的东西:逻辑有没有问题,有没有bug,边界条件考虑到了没有,有没有安全隐患,性能有没有问题,设计合不合理,可维护性怎么样,命名清不清晰,注释够不够,有没有重复代码,有没有更好的实现方式等等。
4. 评审意见要友好
评审的时候提意见要对事不对人,不要说"你这里写得太烂了",要说"这里是不是可以考虑一下某某情况,可能会有问题"。要尊重别人的劳动成果,先肯定做得好的地方,再提改进建议。被评审的人也要虚心接受意见,不要觉得别人挑你毛病是针对你,大家都是为了代码质量,有不同意见可以讨论,不要情绪化。
5. 自动化辅助评审
很多机械的检查可以交给自动化工具来做,比如代码格式检查用ESLint、PHP_CodeSniffer,静态分析用SonarQube,单元测试和集成测试在CI里自动跑,这些都通过了再进入人工评审。这样人工评审就可以专注于逻辑和设计这些机器检查不了的东西,效率更高。
六、其他最佳实践
1. 善用.gitignore
不要把不该提交的东西提交到Git里,比如依赖目录(node_modules、vendor)、环境配置文件(.env)、日志文件、临时文件、IDE配置文件等等。这些东西应该写在.gitignore里,Git会自动忽略它们。每个人的本地环境配置可能不一样,把配置文件提交上去会导致冲突,而且敏感信息(比如数据库密码)提交上去也不安全。
2. 不要提交大文件和二进制文件
Git不适合管理大文件和二进制文件,比如视频、安装包、压缩包这些,提交上去会让仓库变得越来越大,clone和pull都很慢。如果确实需要管理这些文件,可以用Git LFS(Large File Storage),或者放到对象存储里,不要直接提交到Git仓库。
3. 学会用rebase整理提交历史
rebase是一个很强大的命令,能帮你整理提交历史,把多个零散的commit合并成一个,或者修改commit message,让提交历史更清晰。但是rebase有风险,不要在已经推送到远程的公共分支上rebase,会把历史搞乱。只在自己的feature分支上rebase,而且rebase之后要force push(注意是--force-with-lease,更安全)。
4. 写好README和文档
项目的README和文档非常重要,新人接手项目首先看的就是README,要写清楚项目是做什么的,怎么安装怎么运行怎么部署,目录结构是怎样的,有哪些注意事项。代码里的复杂逻辑也要写注释,方便别人理解,也方便几个月后的自己理解。不要觉得写文档浪费时间,好的文档能大大减少沟通成本,提高团队效率。
5. 保护好主分支
在Git平台上要设置主分支的保护规则,不允许直接push到master,必须通过Pull Request合并,而且要至少一个人评审通过,CI检查通过才能合并。这样能防止有人不小心把有问题的代码推到master,也能强制大家走代码评审流程。
七、写在最后
Git工作流最佳实践:从分支策略到代码评审。
Git是一个非常强大的工具,但是工具只是工具,关键还是看人。再好的工作流,如果团队不遵守不执行,那也等于没有。所以团队要达成共识,一起制定适合自己的工作流,然后每个人都严格遵守,这样才能真正发挥Git的作用,提升团队的协作效率和代码质量。
这篇文章分享了分支策略、提交信息、代码评审等方面的一些最佳实践,都是我在实际工作中总结出来的经验,希望能帮大家少踩坑。当然每个团队的情况不一样,大家可以根据自己的实际情况调整,找到最适合自己的工作流。
最后用一句话结尾:"好的Git工作流不是为了约束大家,而是为了让团队协作更顺畅,让代码质量更有保障。"
祝大家的团队都能找到适合自己的Git工作流,协作愉快,代码质量杠杠的!
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录