
简介一份面向开发团队尤其是 Git 使用新人的分支管理规范文档系统梳理 master、develop、feature、bugfix、release、hotfix 六类分支的职责、创建来源与合并去向并结合常用命令介绍命名规则、切换方法、合并时机和发布流程。文档明确功能分支应从 develop 创建、自测通过后合并回 develop普通 bug 从 develop 创建 bugfix 分支修复后同样合并回 develop紧急线上问题从 master 创建 hotfix 分支先合并至 master 打标签上线再合并回 develop发布前从 develop 拉出 release 分支经历测试和缺陷修复后同步合并至 master 和 develop合并后分支应及时清理。压缩包内含 1 个 doc 文档体积约 239KB正文以章节结构展开还包含必读文章推荐、git flow 工具的安装与简化操作以及发布 Release 和 Hotfix 的完整步骤适合技术负责人或团队新人直接作为规范参考。已有 2178 人学习浏览文档基于作者近一年的实战经验沉淀既有理论框架又有可落地细节是搭建团队 Git 协作流程的实用蓝本。1. 分支管理规范不是流程文档是团队的后悔药一个十人不到的研发团队最容易翻车的往往不是代码质量而是 Git 分支乱到没人敢合并。你问某条需求在哪答案要么是“我本地还没推”要么是“好像有个 feature 分支但不记得叫啥了”功能上线后想回滚发现主干上混着没测完的提交根本不敢 revert。GIT 分支流程开发规范解决的就是这件事它不改变你写代码的方式但改变你提交、合并、发布的路径让每一次变更都有迹可循。这篇文章写给正在从“单打独斗”走向“多人协作”的团队也写给想给仓库立规矩却又不知道从哪下手的同学。落地优先不搞理论堆砌。2. 分支模型怎么定先把主干保护起来2.1 为什么主干分支必须稳很多团队刚建仓库时只有一条 main或 master所有人直接往上推推坏了再修。这种模式在小项目里勉强能用一旦并行需求超过两三条主干就成了谁手快谁先合、谁出错谁背锅的赛跑场。所以分支管理规范的第一条原则不是“多建分支”而是“主干要稳”。主干分支只接受经过验证的提交日常开发一律不让直接触达。常见的落法是参考 Git Flow 的骨架但按团队规模做裁剪保留 main 和 develop 作为长期分支feature、release、hotfix 作为短期分支。长期分支的生命周期跟项目走短期分支跟需求或缺陷走合并完之后该删就删。这个模型的优势在于它把“开发中”和“已就绪”两种状态物理隔开main 永远对应线上或即将上线的版本develop 永远对应下一次迭代的集成现场。2.2 五类分支的角色、命名与生命周期定了主干稳定原则之后分支类型和命名规则就成了下一件必须写进规范的事。命名乱是团队协作里最消耗耐心的琐碎问题规范统一后光是看分支名就能判断这条分支在干什么、从哪来、要合到哪去。分支类型命名规范来源合并去向生命周期主干分支main仓库初始化不接受直接推送永久开发分支develop从main切出合并回main永久功能分支feature/编号-描述从develop切出合并回develop需求完成后删除发布分支release/版本号从develop切出合并回main与develop发布完成后删除热修分支hotfix/编号-描述从main切出合并回main与develop修复上线后删除命名里的编号建议直接用需求单号或缺陷单号比如feature/1024-user-login。这样看分支名能回溯到业务上下文之后写提交信息、查历史、找责任人都有依据。描述部分用短横线连接全部小写不要带空格和中文避免在 Windows 和 macOS 上出现换行解析问题。2.3 分支生命周期的两个硬规则分支规范里最容易执行不到位的是清理环节。feature 分支合并进 develop 之后它就已经完成了使命留在远端只会让仓库分支列表越来越长还会让后来的同事误以为这条分支还在维护。两个硬规则值得直接写进团队规范第一条短期分支合并完成后由合并者顺手删除远端分支本地分支在切换回 develop 后用git branch -d清理。第二条分支超过两周没有提交且关联需求已关闭的由仓库管理员确认后强制清理。这两条配合分支保护规则一起用仓库长期保持干净状态新人进来一眼能看懂老人不需要靠记忆找分支。3. 按流程把分支跑起来从创建到热修的命令序列3.1 初始化从空仓库到 develop 分支分支规范落地的前置条件是仓库结构本身符合规范。新仓库第一次提交时先建一个无内容的 README 作为初始提交之后创建 develop 分支这样之后所有 feature 和 hotfix 分支的切换都有干净的起点。# 空仓库初始化先建初始提交再切开发分支 git init touch README.md git add README.md git commit -m chore: 初始化仓库 git branch -M main git checkout -b develop git push -u origin main develop这里第一行git branch -M main把默认分支名统一为 main避免不同成员本地默认名不一致后续 push 时候还要猜。git checkout -b develop从 main 切出开发分支git push -u origin main develop一次把两条长期分支都推到远端并建立跟踪。到此远端仓库就有了 main 和 develop 两条长期分支后续短期分支都从这两条往下切。3.2 功能分支的日常提交、同步与 rebase功能开发阶段最容易出乱子的是“分支越拖越旧”。一个功能写了两周develop 上已经合了别人十几个提交这时候你想再把 feature 合回去冲突规模早已失控。所以规范里要约定功能分支每天至少从 develop 同步一次同步用 rebase 而不是 merge。# 切回功能分支后从 develop 拉取最新提交并变基 git checkout feature/1024-user-login git fetch origin develop git rebase origin/develop # 如果有冲突解决后继续 git add . git rebase --continue命令的含义是把当前 feature 分支上独有的提交挪动到 origin/develop 当前提交之后的快照上让功能分支历史是一条直线。这样做的收益在于合并回 develop 时不会生成多余的 merge commit冲突也被提前分散到每天的同步里而不是最后一天集中爆发。参数说明git fetch只更新远端仓库在本地的记录不改变工作区git rebase origin/develop是变基操作没有把 develop 合入 feature所以不会残留无意义的合并节点。3.3 合并进 develop用 --no-ff 保住需求边界功能开发完成并自测通过后合入 develop。合并方式这里有一个重要的参数选择--no-ff。# 先切到 develop 并同步最新代码 git checkout develop git pull --rebase origin develop # 合并功能分支保留独立提交线 git merge --no-ff feature/1024-user-login git push origin develop--no-ff的含义是不使用快进方式合并即使当前 develop 可以直接指向 feature 分支的末端也强制生成一个 merge commit。这个参数据我的经验值得成为规范标配它保留了一个稳定的“需求提交容器”之后做发布回溯时git log --oneline --graph里能清楚看到某条需求是什么时候进入 develop 的。合并后 push 之前记得先git pull --rebase避免本地 develop 落后远端却强行合并出分叉这个动作看着多余实际上省掉很多“push 被拒”的尴尬。3.4 发布与热修两个特殊流程的命令发布分支和热修分支都是带有明确时效的短生命周期分支但它们的来源和归处完全不同。发布分支从 develop 冻结只修 bug不接新功能热修分支从 main 直接切出解决线上紧急问题后同时合回 main 和 develop防止线下环境漏掉这处修复。# 发布分支从 develop 冻结发布后合并回 main 与 develop git checkout -b release/1.2.0 develop # ... 只修 bug不合新功能 ... git checkout main git merge --no-ff release/1.2.0 git tag -a v1.2.0 -m release 1.2.0 git checkout develop git merge --no-ff release/1.2.0 # 热修分支从 main 切出修复后合并回 main 与 develop git checkout -b hotfix/2099-payment-fix main git commit -m fix: 修复支付回调验签失败 git checkout main git merge --no-ff hotfix/2099-payment-fix git tag -a v1.2.1 -m hotfix 1.2.1 git checkout develop git merge --no-ff hotfix/2099-payment-fix这个流程里最容易漏掉的动作是热修完成后没有合并回 develop。线上发现的问题往往在生产环境才暴露develop 里同样存在这段有缺陷的代码只合 main 不回 develop下次发布时这个 bug 会原样再犯一遍。发布分支同理发布测试中修的几个小 bug 若不留回 develop等于白修。所以热修和发布的合并目标必须是双份的这个靠肌肉记忆不可靠建议写进团队检查单或者 CI 脚本里做自动检测。4. 保护与自动化让规范从“自觉”变成“强制”4.1 分支保护规则前端拦截硬编码配置依赖自觉执行的分支规范总会在周五下午被赶需求的人打破。所以规范要落地成纪律必须在远端仓库配置分支保护规则。常见做法是在 Git 平台的仓库设置里对 main 和 develop 开启“保护分支”禁止直接推送所有变更必须通过合并请求进入。主干分支的 push 权限收窄到仓库管理员甚至设为管理员也不能直接推。单靠这一条规则就能把绝大多数不合规提交挡在仓库之外。保护规则还有一个容易忽略的附加项要求合并请求通过 CI 检查和至少一人评审后才允许合并。这条参数对应的是“已验证”的流程目标CI 检查至少包含构建成功和单元测试通过评审保证至少有一个其他成员看过变更避免“自己写自己合”造成的历史盲区。配置好之后凡是想直接 push main 的人都会收到远端拒绝的提示这个提示本身就是最好的规则教育。4.2 钩子脚本本地先拦一道远端规则管的是 push 那一刻但本地 hook 可以在提交之前就把不合规内容拦下。pre-push 钩子是性价比最高的强化手段它会在git push触发时执行一段脚本按团队规范校验当前分支名和提交信息格式校验不通过就拒绝推送。#!/bin/sh # .git/hooks/pre-push 示例检查分支名和提交信息格式 # 安装方式复制到 .git/hooks/ 目录并添加执行权限 remote$1 url$2 # 获取即将推送的分支名 branch$(git symbolic-ref --short HEAD 2/dev/null) if [ -z $branch ]; then echo 错误: 无法识别当前分支名 exit 1 fi # 检查长期分支只允许 main 和 develop 推送 if [ $branch main ] || [ $branch develop ]; then echo 警告: $branch 是长期分支不允许直接推送 echo 请通过合并请求合入变更 exit 1 fi # 检查短期分支命名的前缀合法性 case $branch in feature/*|release/*|hotfix/*) ;; *) echo 错误: 分支名必须以 feature/、release/ 或 hotfix/ 开头 exit 1 ;; esac # 检查最近一条提交信息是否违反提交格式 last_commit$(git log -1 --format%s) if ! echo $last_commit | grep -qE ^(feat|fix|docs|style|refactor|test|chore):; then echo 错误: 提交信息缺少 type 前缀例如 feat: 加登录弹窗 exit 1 fi exit 0脚本里的三段检查分别对应本章前面的三个规范点长期分支带头保护、短期分支按类型命名、提交信息用约定式格式。执行顺序上这里先从最外层的分支名查起再逐条深入提交信息每一条失败都给出明确的中文提示成员被拦下来的时候知道自己改什么而不是摸不着头脑。这个脚本也有边界要说清楚.git/hooks/目录不随克隆传给下一个开发者需要团队成员手动复制或用一次性的初始化脚本写入配置。如果团队仓库可以接受引入第三方工具也可以用现成的 pre-commit 框架托管同一套钩子但核心逻辑和返回码约定不变。4.3 提交信息规范让 git log 当日报读很多团队管了分支却漏了提交信息。其实提交信息是分支流程的“末梢神经”也是后期回溯问题时最可靠的下钻路径。提交信息不规范git log --oneline就是一篇没有章法的流水账遇到紧急热修根本找不到对应的那条变更。规范的核心是约定式提交的前缀每一条提交信息必须匹配type(scope): 描述这种格式。常用 typefeat表示新功能fix表示缺陷修复docs表示文档变更refactor表示重构test表示测试相关chore表示构建或杂项。scope 可写模块名也可省略描述用一个动词开头控制在五十字符以内。这套格式的好处是脚本可解析、日志可读、发布日志可自动生成。配合前面 pre-push 钩子里的正则校验就能让团队在根上调整到高一致性状态。实际操作中可以在团队文档里放一段示例模板让成员提交时照着写两周后习惯就养成了。5. 分支合并与回溯五个高频翻车点和排查方法5.1 现象rebase 后 push 被远端拒绝这个翻车现场几乎每个团队都经历过一次。成员在 feature 分支上执行git rebase origin/develop之后本地历史被重写接着 push 时远端提示“拒绝推送”。原因是在执行 rebase 之前feature 分支已经被 push 到远端并可能被他人拉取过本地员用自己的新历史覆盖远端Git 认为这是对他人的潜在破坏于是拒绝。解决的方法是 push 时加--force-with-lease这个参数比--force安全一个量级它会先对比远端引用是否还是自己上次 fetch 时的哪个版本只有在远端没有被其他人推进时才会强推从而避免覆盖他人的新提交。血泪经验是rebase 之前先开会知会尽量只 rebase 自己独占的分支共享分支上尽量用git merge origin/develop而不是 rebase。5.2 现象切分支后代码“丢失”提交找不回来这条常发生在直接复制粘贴命令的场景。成员执行git checkout -b feature/xxx切换到新分支时提示本地有未提交改动习惯性用了git checkout .或git stash结果写了半天代码“没了”。如果只是 checkout 切分支改动还留在工作区一旦用了git stash改动被收进暂存堆里git stash pop才能恢复。排查顺序建议是先git stash list看有没有暂存堆再git reflog看分支切换历史reflog 是 Git 的后悔药记录着 HEAD 过去所有移动。如果改动曾经进入历史提交用git reset --hard HEAD{n}就找得回来如果只是未提交的工作区文件回退窗口有限所以最稳的做法是养成提交后再切分支的习惯或者用git stash并立刻在便利贴上记下 stash 编号。这条建议身边的同事已经用了好几年客观上救回过几个需求周期。5.3 现象同一个文件反复冲突怎么解都解不完冲突集中在少量文件上背后一定是格式或依赖层面的问题。最常见的是package-lock.json、yarn.lock、go.sum这类锁文件以及格式化工具全局刷过的文件。多人并行改依赖时每次合并都冲突一次哪怕内容差异只有一两行。处理锁文件冲突的方式是选中其中一边的完整版本回到 develop 重新安装依赖并提交。具体命令是在合并冲突后执行git checkout --theirs package-lock.json或--ours取决于目标分支方向然后重新npm install或yarn install让工具自己纠偏。预防层面把锁文件纳入合并策略必要时用.gitattributes标记为mergeunion但会更冒险建议只在团队熟练掌握以后再启用。5.4 现象ssh 认证失败clone 拉不下仓库分支流程再规范第一步仓库拉不下来说什么都没用。git 使用 SSH 协议时提示权限拒绝常见原因有三类本机缺少公钥、公钥没有添加到远端账号、或者本机存在多个 SSH key 导致用了错误的身份。先排查本机是否有公钥ls ~/.ssh没有就执行ssh-keygen -t ed25519 -C youexample.com生成密钥对。然后复制~/.ssh/id_ed25519.pub内容粘贴到 Git 平台的 SSH 公钥设置页。如果配置了多个密钥需要在~/.ssh/config里按 Host 指定IdentityFile。排查消息上ssh -T gitgit.example.com是一条很直接的连通性测试命令返回欢迎语说明认证链路已通剩下的问题基本只在 HTTPS 跟 SSH 的混用上。5.5 现象保护分支被“绕过”合并记录像雪花一样乱保护规则配置好之后仍然可能遇到不合规的合并记录被推到远端。最常见的路径不是绕过规则而是管理者在合并请求页面勾选了“合并后删除源分支”的同时手工在本地通过git push origin main强推了本地 main保护策略只拦截普通 push 和部分平台上的强推管理员身份下有些行为的判定会放宽。解决方式是收敛权限保护规则里把 main 的强推权限也关掉管理者平时发布只用合并请求或定期从 release 分支同步。另外给团队约法三章线上紧急修复一律走 hotfix 分支并保留合并请求记录到排查问题时才有关键证据链。这两条配合下来绕过的空间基本被堵死。6. 从规范到习惯一条命令守住提交线规范文件写得再漂亮最终都要落到工具链上才能被长期执行。这里分享一个我一直在用的做法把第五章的 pre-push 检查代码封装成一个独立的可执行脚本文件放在项目根目录里的scripts/git-check.sh然后在.git/hooks/pre-push里只保留一行调用。#!/bin/sh # .git/hooks/pre-push 的简化版 # 用它调用团队公共规范脚本避免每个克隆仓库各维护一份 exec sh $(git rev-parse --show-toplevel)/scripts/git-check.sh $这样做的好处是当团队新增一个提交信息前缀类型或者在分支命名规则里增加新约束时只需修改scripts/git-check.sh新克隆的仓库自动拉到最新逻辑。旧仓库由管理员批量执行一次git config core.hooksPath scripts/git-hooks朝core.hooksPath指向统一目录切换之后不需要每个成员手动把 hook 复制到.git/hooks。验证这套检查是否生效最直接的方法是故意推一个不合规的分支比如在本地新建一个test-branch提交一条不带 type 前缀的信息然后 push。命令被拦截说明钩子生效检查项的报错文字也能顺手验证是否足够清晰。一个新成员要独立走完一个需求周期建 feature 分支、每天 rebase develop、提合并请求、等评审、合入、删分支全过程都不需要问“我该推哪个分支”这套规范才算真的立住了。我第一次在团队推行这套规范的时候把 main 保护规则打开的那天两个月里第一次有人跑过来问“为什么我 push 不了了”我告诉他这不是 push 坏了是规则起作用了。之后再也没有人因为误推 main 而在群里道歉。分支流程的价值不是限制动作而是在动作出错的时候给每个人一张可以往回找的路线图。希望帮到你。本文还有配套的精品资源点击获取