Git 面试进阶详解
Git 是分布式版本控制系统,核心是“快照模型”而不是“文件差异模型”。每次提交都记录一组文件快照与父提交关系。
Git 面试进阶详解
一、核心原理(面试官最爱追问)
1. Git 本质是什么
Git 是分布式版本控制系统,核心是“快照模型”而不是“文件差异模型”。每次提交都记录一组文件快照与父提交关系。
2. 三棵树怎么理解
- Working Directory:工作区
- Index(Staging Area):暂存区
- Repository(HEAD 指向的提交):版本库
你执行 add、commit、reset 本质就是在三棵树之间搬运状态。
3. 为什么会有冲突
本质是同一上下文被不同提交修改,自动合并无法确定最终语义,需要人工裁决。
二、merge vs rebase(必答题)
1. merge 的特点
保留分叉和合并历史,不重写已有提交,团队协作更稳妥。
2. rebase 的特点
把当前分支提交“重放”到新基线上,历史更线性,但会改写提交哈希。
3. 实战选型建议
- 公共分支:优先
merge - 个人功能分支整理历史:可用
rebase - rebase 后推送:使用
git push --force-with-lease
三、交互式 rebase(高频细问)
1. 典型用途
压缩碎提交、调整提交顺序、改历史提交信息、删除无效提交。
2. 常用指令
pick:保留reword:仅改 messagesquash:与前一提交合并并编辑 messagefixup:与前一提交合并并丢弃当前 messagedrop:删除提交
3. 冲突处理流程
git rebase -i HEAD~5
# 解决冲突后
git add .
git rebase --continue
# 放弃本次操作
git rebase --abort
四、回滚与恢复(救火能力)
1. reset
适合本地历史整理,按 --soft、--mixed、--hard 决定保留层级。
2. revert
对“已共享历史”更安全,会新增一个反向提交,不破坏原有历史链。
3. reflog
误删、误 reset、误 rebase 的恢复入口。找回 commit hash 后可 reset 回去。
五、定位回归与移除提交
1. 用 git bisect 定位引入问题的提交
当已知一个“正常”的旧提交和一个“异常”的新提交时,bisect 会用二分法缩小范围。开始前应保存工作区,测试命令必须可重复,并明确退出状态:
git bisect start
git bisect bad HEAD
git bisect good <known-good-commit>
# Git 检出中间提交后运行可重复的测试命令
npm test
git bisect good # 当前版本通过
# 或
git bisect bad # 当前版本仍失败
git bisect reset
自动化时可以使用 git bisect run <command>,命令返回 0 表示 good,返回 1 到 127(125 用于 skip)表示 bad;脚本应避免把环境错误误报成 bad。定位结果后先用 git bisect log 记录过程,再退出会话,不要把临时检出的状态直接当成工作分支。
2. 移除或还原指定提交
- 未共享的本地提交可以在
git rebase -i <parent>中把对应行改为drop,或用rebase --onto重组提交。 - 已推送到公共分支时,使用
git revert <commit>生成反向提交;还原合并提交要明确主线父提交(例如git revert -m 1 <merge-commit>)。 - 只有在确认没有其他人基于该分支开发时,才考虑重写远端历史,并使用
git push --force-with-lease而不是无条件--force。
“删除提交”不等于从所有对象中立即抹除数据。误操作时先用 git reflog 和 git show 找到可恢复的引用,再决定 reset、revert 或重写历史。
六、第三方 npm 包的可追溯修补
不要直接编辑 node_modules:安装、清缓存或 CI 重建都会丢失修改。短期修复可用包管理器提供的 patch 机制或 patch-package 生成补丁文件,并把补丁、锁文件和触发原因一起提交;能通过 overrides/resolutions 升级到已修复版本时优先升级。长期维护应提交上游修复,或维护带明确版本和变更记录的 fork。CI 要验证补丁仍能应用,依赖升级后应尽快删除临时补丁。
七、团队协作常见坑
1. 直接强推覆盖他人提交
避免 push --force 盲推,优先 --force-with-lease。
2. 提交粒度太粗
大而杂的提交会显著增加 code review 与回滚成本。
3. 长期不同步主干
功能分支与主干偏差过大,最终一次性冲突成本会陡增。
八、三档口述模板(背诵版)
1. 30 秒版本
Git 我重点掌握的是分支协作和历史治理。团队协作里我优先用 merge 保证稳定性,在个人分支会用 rebase 整理线性历史。发生误操作时,我一般先看 reflog 定位可恢复点,再选择 reset 或 revert,确保既能恢复代码也不破坏团队历史。
2. 2 分钟版本
我一般把 Git 分成三块来回答。第一是协作:功能分支开发、PR 合并、冲突处理和语义化提交。第二是历史治理:个人分支用 rebase -i 清理碎提交,公共分支尽量不用重写历史。第三是故障恢复:本地整理用 reset,线上协作回退用 revert,误删误回退先用 reflog 找历史锚点。这样既保证效率,也保证多人协作安全。
3. 5 分钟版本
我会从“原理、规范、实战”三个维度讲。原理上,Git 是快照模型,理解工作区/暂存区/版本库三棵树后,很多命令本质就清楚了。规范上,我会要求提交粒度小、信息清晰、分支命名可读,并在功能分支周期性同步主干,降低冲突爆发概率。实战上,我常用 rebase -i 做历史整理、cherry-pick 做补丁迁移、revert 做安全回滚,误操作通过 reflog 恢复。面试里我会强调:工具命令不难,难的是在团队协作中做出低风险决策。
九、高频追问标准答法(Q/A)
1. Q: 什么时候必须用 revert 而不是 reset
A: 当提交已经推到远端并被他人基于其开发时,用 revert 更安全,不破坏共享历史。(深入阅读:回滚与恢复)
2. Q: 为什么 rebase 后要 --force-with-lease
A: 因为 rebase 改写了提交哈希,需要强制更新远端;--force-with-lease 能避免误覆盖他人新提交。(深入阅读:merge 与 rebase 的实战选型)
3. Q: stash pop 和 stash apply 区别
A: pop 应用后会删除该 stash;apply 只应用不删除。(深入阅读:临时保存与恢复)
4. Q: 如何减少冲突
A: 缩短分支生命周期、提高同步频率、拆小提交、提前对高风险文件沟通归属。(深入阅读:团队协作常见坑)
5. Q: 你如何设计提交规范
A: 采用语义化前缀(feat/fix/refactor/docs/chore),并要求一条提交只表达一个清晰意图。(深入阅读:日常提交)
十、可以反问面试官的问题
1. 分支策略
你们目前是 Git Flow、Trunk-based,还是简化版 feature-branch?
2. 回滚机制
线上回滚主要依赖 Git 还是 CI/CD 制品回滚?
3. 规范治理
团队是否有 commit lint、分支保护、必需 review 等硬约束?
4. 冲突热点
当前冲突最高发的模块是哪些,是否有 ownership 机制做边界治理?