Git 的正确使用姿势与最佳实践:团队协作和版本控制的最佳实践标题 | 青训营

102 阅读8分钟

前言

Git 已经成为软件开发行业的事实标准,但很多团队在使用 Git 进行协作和版本控制时,仍然存在一些不太好的习惯或做法。本文将结合示例,阐述 Git 的一些最佳实践,帮助读者掌握 Git 的正确使用姿势,在团队协作中发挥 Git 最大的价值。

主要内容包括:

  • Git 流分支管理策略
  • 提交信息编写规范
  • 代码review工作流
  • Git 钩子的使用
  • 对应用进行逻辑划分
  • 合理使用 Git 工具

Git 流分支管理策略

主分支与开发分支

对于一个应用程序,通常会有两个长期分支:

  • 主分支(master):用于部署到生产环境的稳定版本代码
  • 开发分支(develop):用于日常开发工作,包含所有最新代码

主分支永远处于可发布状态,开发分支包含所有未完成和可能存在 Bug 的最新代码。

功能分支

对于一个新功能或修复 Bug,都应该基于 develop 分支创建功能分支,分支名可以使用 feature/xxxbugfix/xxx 前缀表示。

完成开发后,再将功能分支合并回 develop,最后合并到 master 发布。

// 创建功能分支
git checkout -b feature/new_API develop 

// 开发新功能

// 合并回 develop
git checkout develop
git merge --no-ff feature/new_API

// 删除功能分支
git branch -d feature/new_API

发布分支

develop 分支组了一组功能准备发布时,可以从 develop 分支创建发布分支,进行最后阶段的集成测试等工作。

当发布完成后,再将发布分支合并回 masterdevelop

// 从 develop 创建发布分支
git checkout -b release/1.2 develop

// 完成发布前的准备工作

// 合并回 master 完成发布
git checkout master
git merge --no-ff release/1.2 

// 合并回 develop 
git checkout develop
git merge --no-ff release/1.2

// 删除发布分支
git branch -d release/1.2

紧急修复分支

当在 master 发现严重问题时,可以直接从 master 分支创建热修复分支进行修复。

修复完成后,直接合并到 master 和 develop 即可。

// 基于 master 创建热修复分支
git checkout -b hotfix/1.2.1 master

// 进行紧急修复

// 合并回 master 
git checkout master
git merge --no-ff hotfix/1.2.1

// 合并回 develop
git checkout develop 
git merge --no-ff hotfix/1.2.1 

// 删除热修复分支
git branch -d hotfix/1.2.1

小结

  • master 分支用于部署到生产环境
  • develop 分支用于日常开发
  • 功能分支实现新功能后合并回 develop
  • 发布分支用于发布前准备工作
  • 热修复分支用于紧急修复生产问题

提交信息编写规范

良好的提交信息对代码重构和日志输出都大有益处。通常要遵循以下规范:

  • 使用祈使语气,例如"fix bug" 而不是 "fixed bug"或"fixes bug"
  • 首行不超过 50 个字符,可以加描述,不超过 72 个字符
  • 描述可分多行,每行不超过 72 个字符
  • 使用 # 分割提交类型、范围、主题,例如:
#fix 账单模块 提交信息示例

常用的提交类型:

  • feat: 新增功能
  • fix: 修复缺陷
  • docs: 文档变更
  • style: 代码格式调整
  • refactor: 代码重构
  • perf: 性能优化
  • test: 测试用例修改
  • build: 影响构建或依赖项的更改
  • ci: 对 CI 配置或脚本的更改
  • chore: 对构建过程或辅助工具和库的更改
  • revert: 恢复先前的提交

代码 Review 工作流

代码评审(Code Review)是保证代码质量非常重要的一步。一般流程是:

  1. 开发人员在自己的分支完成代码编写,并推送到远程仓库

  2. 在 GitHub 等平台发起 Pull Request,请求将代码合并到 develop 分支

  3. 由其他开发人员对修改代码进行审查,提出修改意见

  4. 开发人员根据意见进行调整optimize,直到PLURALITY通过审查

  5. 合并 Pull Request,完成代码合并

在提交 Pull Request 时,需要提供充分的提交信息和注释,方便 reviewer 理解代码的作用。审查人需要对以下方面进行检查:

  • 功能代码是否实现预期的业务需求
  • 是否存在安全性问题
  • 是否符合项目的代码规范
  • 是否存在冗余或不必要的代码
  • 是否存在清晰的技术债务说明
  • 代码中的注释是否到位

通常一个 Pull Request 不要包含太多的提交和改动,以保证 reviewer 可以合理分配时间进行充分查看。

如果修改涉及复杂的业务逻辑,需要在提交 PR 前与团队其他成员进行设计评审,以期望获得更好的解决方案。

Git 钩子的使用

Git 钩子可以在指定的 Git 操作执行前或执行后触发自定义脚本。

例如在提交前执行单元测试和代码规范检查:

#!/bin/sh

go test ./...
gofmt -l -w .
git add .

也可以在推送后自动部署到测试服务器:

#!/bin/sh

git push origin develop
./deploy.sh test

placing executable hook scripts in .git/hooks目录下,命名需要符合如下规范:

  • pre-commit:提交前触发
  • prepare-commit-msg:生成提交信息前触发
  • commit-msg: 提交时触发
  • post-commit:提交后触发
  • pre-rebase:衍合前触发
  • post-checkout:切换分支后触发
  • post-merge:合并后触发
  • pre-push:推送前触发
  • pre-auto-gc:垃圾回收前触发

使用钩子可以很大程度地优化开发流程,提高代码质量。

对应用进行逻辑划分

随着业务复杂度增加,代码应合理地进行模块化,常见的模块划分:

  • handler:用于请求的接收和响应
  • service: 核心业务逻辑
  • dao: 数据访问层,与数据库交互
  • dto: 数据传输对象,用于不同模块间传递数据
  • config: 配置相关代码
  • common: 公共功能组件
  • test: 测试模块

针对不同模块使用不同的包,合理划分目录结构:

├── handler
│   └── user.go 
├── service
│   └── user.go
├── dao
│   └── user.go
├── dto
│   └── user.go
├── config
│   └── config.go
├── common 
│   └── utils.go
└── test
    └── service
        └── user_test.go

通过模块化划分,可以提高代码的内聚性和复用性。handler 和 controller 负责流程控制,service 实现业务逻辑,dao 封装数据库交互,dto 定义数据结构。

合理使用 Git 工具

  • Git Flow:实现 Git 流分支管理策略的工具
  • Git LFS:管理大文件存储的工具
  • Git Hooks:实现 Git 钩子自动化的工具
  • Git Stash:保存和恢复工作目录的工具
  • Git Cherry-pick:选择性地把提交应用到其他分支
  • Git Rebase:合并分支时保持线性提交历史
  • Git Submodule:管理项目依赖关系的工具

合理使用这些工具,可以大幅提高团队的协作效率。

思考

在日常开发和团队协作中,我们经常会遇到代码管理和版本控制的问题。使用Git可以很好地解决这些问题,但是如果没有正确的使用姿势,Git的效率和价值就无法真正发挥出来。

  1. 分支管理策略直接影响协作效率。常见的Git流是非常好的实践,它在保证主分支稳定性的同时,允许开发分支进行日常开发工作。但策略也不能一成不变,需要根据团队大小和项目特点进行适当调整。
  2. 规范的提交信息对代码管理非常重要。通过prefixes可以快速区分提交类型,从而可以方便地生成changelog和发布日志。但是也需要控制好提交粒度,过于频繁和过于庞大的提交都会降低review效率。
  3. 代码review是非常关键的一步。它不仅能提高代码质量,也可以增进团队成员之间的交流与理解。 reviewer需要对代码变更采取负责任的态度,确保重构或新功能的实现符合预期。同时也要CONTROL好review的工作量,避免review成为单纯的把关之举。
  4. Git钩子的使用可以极大地优化工作流程,比如利用pre-commit执行测试和lint可以及早发现问题,post-commit实现持续集成可以快速验证新代码。但钩子也需要慎重设计,过于频繁和复杂的钩子会成为开发阻碍。
  5. 模块化设计和项目目录结构直接影响多人协作的效率。合理的拆分可以减少相互依赖,同时也容易扩展和维护。除功能模块化外,代码和配置也需要区分开,测试用例需要独立存放。这些在设计时都需要考虑到。
  6. Git工具的使用需要因人和项目而异。比如对新手来说,Git Flow可以简化分支管理,但对于老手可能过于繁琐。子模块对依赖管理很有帮助,但也容易引入问题。正确使用需要结合实际场景。

总之,Git最佳实践并非一成不变,它需要根据团队实际情况不断进化和调整,才能发挥最大效用。同时团队成员也需要共同努力,才能将这些实践真正应用到开发过程中去。只有持续改进,我们才能在版本控制的道路上越走越顺。

总结

  • 分支管理策略很重要,master 存放发布版本,develop 用于日常开发
  • 编写规范的提交信息和 PR 描述对协作非常重要
  • 代码评审需要仔细检查,避免引入问题
  • Git 钩子可以自动执行脚本优化开发流程
  • 模块化划分有助于提高内聚性和复用性
  • 合理运用 Git 工具可以提效协作

掌握这些 Git 最佳实践,可以帮助开发团队建立高效的协作方式,从而更好地发挥 Git 在版本控制中的价值,实现产品的迭代开发。