模块五:工程质量与生产部署 | 第04讲:Git 协作全流程——提交规范、分支策略、冲突处理不踩坑
本讲定位:把「压缩包互传」升级为可审计、可回滚、可并行的 Git 协作;覆盖 Conventional Commits、Trunk-Based / GitHub Flow、PR 与 Code Review、冲突解决,以及 AI 辅助 Git 的安全边界。
项目锚点:VibeNote 单仓库(Next.js 全栈),远程托管以 GitHub 为例。
延伸阅读:课程内容/6.5、reference/advanced/11-git-collaboration.md。
一、Git 到底解决了什么
没有 Git 的协作是「最终版_真的最终版_再改剁手版.zip」。Git 给你三件礼物:
- 时间旅行:每一次提交都是可命名的检查点,随时对比差异。
- 并行宇宙:分支让多人同时推进而不互相覆盖。
- 可信同步:远程仓库(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:文档-onlyrefactor:重构无行为变化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(个人与小团队极友好)
main始终保持可部署(或至少可合并)。- 新工作从
main拉短生命周期分支:feat/xxx、fix/yyy。 - 推送 → 开 PR → CI 绿 → Review → 合并 → 删除分支。
- 部署通常绑定在
mainpush(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)。
- 风险:迁移、兼容、回滚方式。
- 测试:如何验证(截图、用例链接)。
- Checklist:
pnpm test、pnpm 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(团队需统一偏好)
出现冲突后:
- 打开冲突文件,理解双方意图。
- 手工合成正确逻辑,删除冲突标记。
git add→git merge --continue或git rebase --continue。- 跑测试。
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、.next、coverage- 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 --force到main。 - 盲目接受「解决冲突」而不读合并结果——极易合成逻辑互斥代码。
- 把含有密钥的片段贴进聊天工具再「顺便提交」。
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 的协作约定(示例团队宪章)
- 默认分支
main保护:必须通过 PR + 1 approve(solo 可先关闭,留钩子)。 - 分支命名:
feat/*、fix/*、chore/*。 - 提交遵循 Conventional Commits。
- 每个 PR 必须关联 issue 或产品文档段落。
- 合并策略:Squash merge(历史干净)或 Merge commit(保留分支细节)二选一,全团队统一。
十、思考题
- 为什么「线性历史」在大型团队里更利于
git bisect? - 何时应该选择 Squash merge,何时应该保留分支上的多个 commit?
- 如果你 rebase 了已推送分支,正确的后续命令是什么?为什么需要
--force-with-lease? - 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
密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。密钥、备份、监控,是独立产品的三件套,缺一则夜不能寐。