5.4 Git 协作全流程——提交规范、分支策略、冲突处理不踩坑

0 阅读19分钟

模块五:工程质量与生产部署 | 第04讲:Git 协作全流程——提交规范、分支策略、冲突处理不踩坑

本讲定位:把「压缩包互传」升级为可审计、可回滚、可并行的 Git 协作;覆盖 Conventional CommitsTrunk-Based / GitHub FlowPR 与 Code Review冲突解决,以及 AI 辅助 Git 的安全边界
项目锚点:VibeNote 单仓库(Next.js 全栈),远程托管以 GitHub 为例。
延伸阅读课程内容/6.5reference/advanced/11-git-collaboration.md


一、Git 到底解决了什么

没有 Git 的协作是「最终版_真的最终版_再改剁手版.zip」。Git 给你三件礼物:

  1. 时间旅行:每一次提交都是可命名的检查点,随时对比差异。
  2. 并行宇宙:分支让多人同时推进而不互相覆盖。
  3. 可信同步:远程仓库(GitHub)成为单一事实来源,讨论围绕 commit 与 PR,而不是微信语音。

在 Vibe Coding 中,AI 会频繁产出大块 diff——没有清晰分支与提交粒度,Review 成本会爆炸,误合并风险陡增。

flowchart LR
    subgraph Local["本地工作区"]
        W[Working Tree]
        I[Index / Staging]
        R[本地仓库 .git]
    end
    W -->|git add| I
    I -->|git commit| R
    R -->|git push| Remote[(GitHub)]
    Remote -->|git pull / fetch+merge| R

二、Conventional Commits:让历史「可读可机器解析」

2.1 基本格式

<type>(<scope>): <subject>

<body>

<footer>

常用 type

  • feat:新功能(VibeNote:星标笔记)
  • fix:缺陷修复
  • docs:文档-only
  • refactor:重构无行为变化
  • test:测试
  • chore:构建/工具链(升级依赖锁文件)

示例:

feat(notes): add star toggle on list row

- add API PATCH /api/notes/:id/starred
- update list UI with optimistic update

Closes #128

2.2 为什么值得坚持

  • CHANGELOG 自动生成semantic-release / 手工也可)。
  • bisect 更快git bisect 时 subject 一眼能懂。
  • 团队协作:Reviewer 从提交消息就知道风险面。
gitGraph
    commit id: "chore: init"
    commit id: "feat(auth): login"
    branch feature/notes
    checkout feature/notes
    commit id: "feat(notes): crud"
    commit id: "fix(notes): search"
    checkout main
    merge feature/notes
    commit id: "chore(release): v1.2.0"

三、分支策略:GitHub Flow vs Trunk-Based

3.1 GitHub Flow(个人与小团队极友好)

  1. main 始终保持可部署(或至少可合并)。
  2. 新工作从 main 拉短生命周期分支:feat/xxxfix/yyy
  3. 推送 → 开 PR → CI 绿 → Review → 合并 → 删除分支。
  4. 部署通常绑定在 main push(Vercel 默认如此)。

适合:VibeNote 早期快速迭代、单人 + 偶发贡献者。

3.2 Trunk-Based(强调小步快跑)

  • 分支极短,甚至一天多次合入 main;大功能用 feature flag 隐藏。
  • 强调持续集成与强自动化测试(与第02讲呼应)。

适合:熟练团队、CI 很稳、愿意投资标志位体系。

3.3 GitFlow(长分支模型)

develop / release/* / hotfix/*——对独立产品早期往往过重;当你有并行版本线与严格发版窗口再考虑。

建议:VibeNote 现阶段选 GitHub Flow + 严格 PR,最省心智。


四、PR 工作流:把 Review 变成产品质量阀门

PR 描述模板要素

  • 动机:用户问题或指标。
  • 方案:关键设计决策(为何不用 B)。
  • 风险:迁移、兼容、回滚方式。
  • 测试:如何验证(截图、用例链接)。
  • Checklistpnpm testpnpm lint、环境变量文档已更新。

Review 关注点(全栈)

  • 权限与数据隔离(别人的笔记不可见)
  • N+1 查询、索引、分页
  • 前端可访问性(表单 label、键盘流)

五、冲突解决:别慌,这是合并算法在求助

5.1 典型场景

两人改同一文件的相邻行;或一人重命名文件,另一人修改旧路径——Git 无法自动裁决,标记 <<<<<<<

5.2 标准流程

git fetch origin
git checkout feature/notes
git merge origin/main
# 或 git rebase origin/main(团队需统一偏好)

出现冲突后:

  1. 打开冲突文件,理解双方意图。
  2. 手工合成正确逻辑,删除冲突标记。
  3. git addgit merge --continuegit rebase --continue
  4. 跑测试。

5.3 Rebase vs Merge

  • Merge:保留分叉历史,直观但图乱。
  • Rebase:线性历史,更清晰;不要 rebase 已推送且他人基于其工作的公共分支
flowchart TD
    C[发生冲突] --> R{是否能拆分提交?}
    R -->|是| S[拆分 commit 降低冲突面]
    R -->|否| M[与对方同步上下文 / 语音对齐]
    M --> H[手工合并保留双方意图]
    H --> T[跑测试]
    T -->|绿| P[push / PR 更新]
    T -->|红| H

六、.gitignore 与安全红线(再强调)

必须忽略:

  • .env*(除 .env.example
  • .vercel 本地配置(若含敏感)
  • node_modules.nextcoverage
  • Playwright test-results/playwright-report/

AI 协作提示:在 AGENTS.md 或项目规则写清:「禁止把 .env 加入提交」。


七、Git with AI:推荐姿势与禁忌

7.1 推荐

  • 让 AI 解释 git diff,生成 PR 描述。
  • 让 AI 根据测试失败日志建议下一小步修复,你手动应用 patch。
  • 用 AI 生成 commit message(仍需你核对 scope)。

7.2 禁忌

  • 让 AI 直接 git push --forcemain
  • 盲目接受「解决冲突」而不读合并结果——极易合成逻辑互斥代码。
  • 把含有密钥的片段贴进聊天工具再「顺便提交」。

7.3 可运行:交互式 rebase 备忘

# 最近 3 个提交整理(示例)
git rebase -i HEAD~3
# 在编辑器中将 pick 改为 squash/fixup 等

八、实用片段:常用命令速查

# 查看漂亮日志
git log --oneline --graph --decorate --all -n 20

# 找出谁改了某行
git blame app/api/notes/route.ts

# 暂存手头工作切换分支
git stash push -u -m "wip notes"
git checkout main
git stash pop

八点五、Cherry-pick 与 hotfix:线上救火怎么走?

main 已坏,但你想只带走某个修复 commit:

git fetch origin
git checkout main
git pull
git cherry-pick <sha>

注意:cherry-pick 可能引入冲突;解决后同样要跑测试。对 VibeNote 这种产品,更推荐fix/ 分支修完走 PR,即使紧急也要保留最小审查窗口(哪怕 reviewer 是你自己隔两小时再看一遍)。


八点六、大文件与 LFS:笔记附件上线后会遇到的坑

一旦 VibeNote 支持图片/音频,仓库体积会暴涨。策略:

  • 二进制不要进 Git;走对象存储。
  • 若必须版本化大文件,使用 Git LFS,并在 CI 限制拉取成本。

八点七、Monorepo 与 submodule:别让自己陷入维护地狱

如果你把编辑器 SDK、共享 UI 拆到多个仓库,早期会爽,后期合并成本会炸。个人产品建议:单仓优先;确需复用,抽 packages/* 本地 workspace。


八点八、PR 里的「AI diff 审查清单」

当 diff 主要来自 AI,Reviewer 应额外关注:

  • 是否无意改了格式化配置导致全文件抖动?
  • 是否引入新的 any@ts-ignore
  • 是否把业务规则写进组件而不是服务层(降低可测性)?
  • 是否偷偷加了 eval / new Function / 动态 require

八点九、提交粒度:什么时候该拆分 commit?

一条 PR 里只有一个巨型 commit,bisect 会失效。建议:

  • 每个独立可回滚步骤一个 commit(重构与功能分离)。
  • 若已合成一团,可用 git reset --soft 重新拆分(谨慎,先备份分支)。

八点十、从「个人习惯」到「团队协议」:最小文档模板

CONTRIBUTING.md 写清:

  • 分支命名、commit 规范、PR 必填项
  • 如何本地跑 pnpm test / pnpm e2e
  • 冲突解决默认用 merge 还是 rebase(二选一)

这三段话能避免 80% 的协作摩擦。


九、与 VibeNote 的协作约定(示例团队宪章)

  1. 默认分支 main 保护:必须通过 PR + 1 approve(solo 可先关闭,留钩子)。
  2. 分支命名:feat/*fix/*chore/*
  3. 提交遵循 Conventional Commits。
  4. 每个 PR 必须关联 issue 或产品文档段落。
  5. 合并策略:Squash merge(历史干净)或 Merge commit(保留分支细节)二选一,全团队统一。

十、思考题

  1. 为什么「线性历史」在大型团队里更利于 git bisect
  2. 何时应该选择 Squash merge,何时应该保留分支上的多个 commit?
  3. 如果你 rebase 了已推送分支,正确的后续命令是什么?为什么需要 --force-with-lease
  4. Code Review 时,你发现 AI 生成的代码通过了测试但可读性极差,你会在 PR 里坚持什么底线?

十一、本节小结

  • Git 的本质是协作协议 + 时间线数据库
  • Conventional Commits 让历史人类可读、机器可解析
  • VibeNote 早期优先 GitHub Flow + PR + CI
  • 冲突解决的目标是合成正确业务语义,不是「选一边」。

十二、下讲预告

第05讲:从 localhost 到公网——Serverless 部署一次讲清
历史干净了,代码该上云了。下一讲逐步拆解 Vercel 部署环境变量Preview Deployment自定义域名Serverless Functions 与 Edge Runtime 在 Next.js 14 中的边界,让 VibeNote 真正拥有 7x24 的 URL。


课后动作:给你当前仓库最近 5 条 commit 写「如果重来,subject 应如何改成 Conventional Commits」的对照表,贴进团队文档草稿。


补篇:rebase 冲突的心理建设

冲突不是 Git 惩罚你,是 Git 请求你显式决策。深呼吸,逐段阅读,不懂就问原作者。AI 可辅助解释 diff,但不要让它替你承担合并责任。

补篇:PR 小步策略

200 行以内的 PR 更容易被认真 review。大块功能拆分成可合并切片,即使 solo 也受益:未来的你会感谢现在的你。

补篇:标签与发版

git tag v5.0.0 标记对外版本,CHANGELOG 从 tag 生成或手工维护。用户问「你修了吗」你能指向版本号。

补篇:hooks:husky + lint-staged

提交前自动格式化与单测 smoke,把低级错误挡在本地。注意别把重 E2E 放 pre-commit,否则你会想关掉 hooks。

补篇:CODEOWNERS

GitHub CODEOWNERS 让敏感目录必须特定人 review。个人项目可省略,但一旦协作立即加。

补篇:结语

Git 是时间线,协作是共识;共识要靠流程,不靠运气。


精读延展:工程化的「慢变量」

工程化里真正改变命运的往往是慢变量:习惯、流程、清单、自动化。它们不像新功能那样在演示视频里闪闪发光,却决定你在第六个月还能不能持续交付。VibeNote 这类产品的竞争,表面是功能,底层是可靠性与迭代效率。把每一讲的知识点写成你可执行的规则文件,比收藏一百篇文章更有用。

精读延展:独立开发者的「风险预算」

你不可能同时买到所有保险,所以要明确风险预算:本周最不能承受的是数据泄露、服务不可用、还是成本失控?把预算花在对应加固上,其他的先记录为「已知风险」。这比假装自己什么都防住了更诚实,也更专业。

精读延展:从教程到产品的距离

教程代码默认跑在 happy path;产品代码默认会遇到蠢问题、坏网络、恶意输入与误操作。模块五的意义,就是把你从教程态推进到产品态:你会开始问「如果失败呢?」「如果被攻击呢?」「如果同事离职呢?」这些问题不浪漫,但决定你能不能靠作品吃饭。

精读延展:与用户的信任契约

用户把笔记交给你,是信任契约。契约内容包括可用性、隐私、透明度与纠错机制。工程措施是契约的底层支撑:备份、监控、安全响应、版本回滚。你可以把契约写得很短,但不能心里没有。

精读延展:把知识变成肌肉记忆

看完专栏不等于学会。请把本模块至少三条规则落实进仓库:例如 .env 纪律、一个 E2E、一个 requestId。肌肉记忆来自重复执行,而不是重复阅读。

精读延展:面向下一阶段的接口

当你完成模块五,你就为增长、商业化、协作功能留下了「干净的接口」:你不会在广告接入时才发现安全头拦了一切;也不会在招聘兼职时才发现没有测试与 PR 规范。提前支付成本,是在给未来打折。


终篇延展:Git blame 与「谁改了这行」

git blame 不是追责工具,是学习工具:看懂历史决策背景再改代码,冲突会少很多。

终篇延展:大文件冲突

二进制与锁文件冲突不要手工合并,通常选择一方再 pnpm install 重生。把规则写清楚,团队少流血。

终篇延展:PR 模板里的「风险自评」

让作者在 PR 勾选:是否涉及鉴权、是否涉及迁移、是否需要数据回填。Reviewer 一眼知道把注意力放哪。

终篇延展:每周合并节奏

小团队可以定「周二四合并窗口」,减少永远合不进去的长分支。

终篇延展:Git worktree(进阶)

并行处理 hotfix 与 feature 时,worktree 能救急;但要小心别在不同 worktree 里跑同一个 dev server 端口。

终篇延展:收束

协作的本质是信息同步;Git 与 PR 是同步协议,不是装饰品。

诵读延展 1

把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。把专栏知识映射成仓库里的真实改动,才算完成学习闭环。

诵读延展 2

独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。独立开发最怕的是‘看过等于会了’;用 issue 与 commit 给自己留证据。

诵读延展 3

工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。工程习惯是复利:第一周痛苦,第二个月麻木,第六个月碾压。

诵读延展 4

别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。别低估文档:未来的你是团队里最贵的合作者。

诵读延展 5

安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。安全、测试、日志、协作、部署,是同一套‘可交付’语言的五种方言。

诵读延展 6

当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。当你能向非技术合作者解释清楚回滚路径,你的工程能力已经进阶。

诵读延展 7

产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。产品价值=功能×可靠性×迭代速度;模块五主要拉升后两项。

诵读延展 8

遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。遇到争议,用数据与日志说话,不要用音量说话。

诵读延展 9

把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。把‘临时方案’三个字从口头语里删掉,改成‘带截止日的技术债’。

诵读延展 10

VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。VibeNote 是练手场,也是作品场:用同样标准要求自己。

诵读延展 11

每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。每一次线上事故,都是一次免费且昂贵的培训;写复盘才不浪费学费。

诵读延展 12

别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。别等‘有空再做测试’;测试是给你空出时间的机器。

诵读延展 13

密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。