知

模块四 · 协作与表达

第 11 / 14 节18 分钟阅读型

Git 与协作:分支模型、撤销与代码评审

Git 的难点不是命令,而是"每个操作影响哪一层"。这一节讲清四个区、四种撤销、两种分支模型,以及一次合格的 PR 应该包含什么。

读完这一节,你能做到

  1. 用"四个区"解释任何一条 git 命令在改什么。
  2. 在 merge、rebase、reset、revert 之间做出安全选择。
  3. 独立解决一次冲突,并判断该保留谁的改动。
  4. 写出可评审的提交与 PR 描述。

一、四个区:所有命令都在这张图上

工作区(你编辑的文件)
  ↓ git add
暂存区(index,下一次提交的内容)
  ↓ git commit
本地仓库(.git 里的提交历史)
  ↓ git push
远程仓库(origin)

反方向的三个命令:

命令影响安全性
git restore <file>用暂存区/HEAD 覆盖工作区会丢失未提交修改
git restore --staged <file>把文件移出暂存区安全
git reset --soft HEAD~1撤销提交,改动留在暂存区安全
git reset --hard HEAD~1撤销提交并丢弃改动危险,不可恢复

记住一句话:reset 改的是历史,revert 改的是内容。已推送到共享分支的提交,只能用 revert,不能用 reset。

二、merge、rebase、reset、revert

命令做什么历史形态适用
merge新建合并提交,保留分支拓扑有分叉合入主分支、保留真实历史
rebase把当前分支的提交"重放"到目标分支之后线性个人分支同步主干、提交前整理
reset移动当前分支指针重写本地撤销,未推送
revert新建一个"反向提交"追加已推送的提交回滚

rebase 的代价是改写提交哈希。如果别人已经基于你的分支工作,rebase 后他们必须重新拉取,否则会产生重复提交。所以:

  • 个人分支可以 rebase。
  • 共享分支不要 rebase。
  • 已经 push 的分支如果必须 rebase,要用 --force-with-lease 而不是 --force,前者会在远端有他人提交时拒绝覆盖。

三、冲突:不是"选一边"那么简单

冲突的本质是同一文件的同一区域被两边修改。解决步骤:

  1. git status 看清哪些文件冲突。
  2. 打开文件,找到 <<<<<<<、=======、>>>>>>> 三段标记。
  3. 理解两边的意图,决定保留、合并还是重写。
  4. 删除标记,运行测试。
  5. git add 标记已解决,继续 merge --continue 或 rebase --continue。

三条经验:

  • 不要直接选 "ours" 或 "theirs",先看两边为什么改。选错边通常能在测试阶段发现,但语义冲突测不出来。
  • rebase 冲突会逐个提交解决,merge 冲突只解决一次。提交多时,rebase 更累。
  • 冲突解决后一定要跑测试。Git 只保证文本合并没有标记,不保证逻辑正确。

预防冲突的办法比解决更重要:小步提交、频繁同步主干、避免多人同时改同一个大文件。

四、两种分支模型

维度Git FlowTrunk-Based
长期分支main + develop + release + hotfix只有 main
分支寿命长短(1-2 天)
发布节奏定期发布持续部署
适合有明确版本周期的产品SaaS、持续交付团队
代价分支多、合并痛依赖自动化测试与特性开关

判断标准:发布节奏与自动化程度。没有可靠的 CI 与测试,Trunk-Based 会把主干变成事故现场;有完善流水线还坚持 Git Flow,则会被合并成本拖慢。

中间路线很常见:主干 + 短生命周期特性分支 + 发布标签。名字不重要,关键是分支寿命短、合并频繁。

五、提交与 PR 的规范

Conventional Commits:

feat(order): 支持按状态筛选
fix(auth): 修复 token 过期后未跳转登录
refactor(api): 抽出统一请求层
docs(readme): 补充本地启动说明

格式是 类型(范围): 描述。收益不是"好看",而是:

  • 能自动生成 changelog。
  • 能按类型过滤 review 重点。
  • 回滚时能快速定位相关提交。

一次合格的 PR 应包含:

部分内容
标题一句话说明改动,与 commit 规范一致
背景为什么要改,关联的 issue
改动改了哪几块,关键决策与取舍
验证怎么测的,截图/录屏/指标
风险影响范围、回滚方式

Review 时优先看:边界条件、错误处理、并发与竞态、权限校验、测试覆盖。不要在第一轮纠结命名与格式,那些交给 lint。

六、三个真实场景

场景一:提交信息写错(未推送)

git commit --amend -m "feat(order): 支持按状态筛选"

只改最近一次,且未推送时安全。

场景二:误把密钥提交了

git rm --cached .env
echo ".env" >> .gitignore
git commit -m "chore: 移除误提交的环境变量"

注意:这只能让后续提交不含该文件,历史里仍然有。真正的补救是立即轮换密钥,必要时用 git filter-repo 重写历史并通知所有协作者。

场景三:线上出问题,要回滚一个提交

git revert <commit>

生成一个反向提交,历史保留,适合共享分支。回滚后要重新验证,因为后续提交可能依赖被回滚的代码。

七、常见坑

  1. 在共享分支上用 reset --hard 强推,覆盖别人的提交。
  2. 用 --force 而不是 --force-with-lease,把远端新提交冲掉。
  3. 冲突时无脑选一边,测试没覆盖语义问题。
  4. 一个 PR 改 30 个文件,评审只能看个大概。
  5. 提交信息写"fix bug",半年后没人知道修了什么。
  6. .gitignore 写得晚,node_modules 与构建产物进了历史。
  7. 把密钥提交后又只删文件,没有轮换密钥。

八、动手任务:自写 → AI 写 → 对比 → 取舍

四步不跳:① 自己写(限时,关掉补全)→ ② 让 AI 写同一题 → ③ 逐条比对 → ④ 说出保留谁的写法。 完整动作与记录模板见《AI 协作与代码评审》。

① 自己写

  1. 在一个练习仓库里,分别用 merge 与 rebase 同步主干,对比 git log --graph。
  2. 故意制造一次冲突,用三种方式解决(保留本地、保留远端、手工合并),并记录差异。
  3. 把最近三个提交用 rebase -i 整理成一个,写清提交信息。
  4. 给一个 PR 写完整的描述,包含背景、改动、验证与回滚方案。

② 让 AI 写同一题

把第 2 题(撤销与整理历史)交给 AI,补一句 说清每一步能不能撤回,已推送的分支怎么办。

③ 对比要盯的点

  • 它给了 reset --hard 却没提示风险吗?那是不可恢复的本地改动。
  • rebase 已推送分支它警告了吗?改写公共历史会害到所有人。
  • reflog 它提了吗?这是最后的救命索。

④ 一句话取舍

照它给的命令执行,哪一步之后你就找不回原来的提交了?

九、自测

  1. 四个区分别是什么,add 与 commit 各改变哪一层?
  2. merge 与 rebase 的历史差异是什么?
  3. 已推送的提交为什么不能用 reset 回滚?
  4. 冲突解决后为什么必须跑测试?
  5. Git Flow 与 Trunk-Based 的判断标准是什么?

参考答案要点:工作区/暂存区/本地/远程;分叉 vs 线性;会改写历史影响他人;Git 只保证文本合并;发布节奏与自动化程度。

附:命令速查表

日常真正用到的命令并不多,按场景记比按字母记有用:

场景命令说明
看当前状态git status -sb精简模式,带分支信息
看改了什么git diff / git diff --staged工作区 / 暂存区
看提交历史git log --oneline --graph -20图形化最近 20 条
看某行是谁改的git blame -L 10,20 file排查“为什么这么写”
找引入 bug 的提交git bisect start/good/bad二分法,回归神器
临时保存改动git stash push -m "wip"切分支前用
只挑一个提交git cherry-pick <hash>热修复常用
撤销工作区修改git restore <file>不可恢复
撤回已提交未推送git reset --soft HEAD~1改动留在暂存区
回滚已推送git revert <hash>安全
看远端分支git branch -r / git remote -v确认推送目标
清理已删分支git fetch -p删除远端已不存在的追踪分支

一个容易被低估的命令是 git bisect。当不知道哪个提交引入的 bug 时,手动翻历史可能要看几十条;二分法在 100 个提交里只需 7 次验证就能定位。配合 git bisect run npm test 还能自动跑。

最后提醒:git push --force 不要出现在团队命令历史里。确需改写已推送的个人分支时,用 --force-with-lease,它会先检查远端是否有人推了新提交,减少覆盖别人的风险。

配套题目

★ 越多越该先背;点题目可看完整答案与深入版。

提示:读完可以顺手做几道对应题目,检验是否真的理解