第 2 章 · 03 进阶、性能与动手练习


文档摘要

第 2 章 · 03 进阶、性能与动手练习 本节摘要:本节回答两个进阶问题:跨平台团队如何用 gitattributes 消除换行符之争;十万文件的 monorepo 为什么慢、如何用 fsmonitor/manyFiles/maintenance/sparse checkout 提速。最后揭晓 git status 的内部机制(两次 diff + 哈希缓存),并以三个动手练习收尾:首次提交、创建分支、squash 提交。 学习目标 说出 gitattributes 的用途并给出换行符示例。 说出 monorepo 变慢的根因与三种优化手段。 解释 git status 如何工作、为什么还能保持较快。 独立完成三个动手练习并回答思考题。

第 2 章 · 03 进阶、性能与动手练习

本节摘要:本节回答两个进阶问题:跨平台团队如何用 gitattributes 消除换行符之争;十万文件的 monorepo 为什么慢、如何用 fsmonitor/manyFiles/maintenance/sparse checkout 提速。最后揭晓 git status 的内部机制(两次 diff + 哈希缓存),并以三个动手练习收尾:首次提交、创建分支、squash 提交。

学习目标

  1. 说出 gitattributes 的用途并给出换行符示例。
  2. 说出 monorepo 变慢的根因与三种优化手段。
  3. 解释 git status 如何工作、为什么还能保持较快。
  4. 独立完成三个动手练习并回答思考题。

一、gitattributes:跨平台换行符

Windows 用 \r\n 换行,Unix/Linux 用 \n。若不加控制,同一文件在两边反复提交会制造噪音差异。

# .gitattributes * text=auto

效果:Windows 检出 \r\n、Unix 检出 \n,仓库内统一存储——各行其道,库里归一

二、monorepo 性能问题与优化

根因

许多 Git 操作依赖文件系统状态。git status 要做两次 diff(HEAD↔暂存区、暂存区↔工作目录),每次都要对海量文件执行 lstat() 系统调用——几十万文件时,一次 status 可能耗时数秒甚至分钟。

优化三件套

手段 机制
fsmonitor(内置,配合 Watchman) 起守护进程持续监视工作目录变更并缓存;git status 不再全盘扫描,直接读缓存状态
feature.manyFiles true 同时开启两项:index.version=4(索引路径前缀压缩)+ core.untrackedCache=true(记录文件 mtime,扫描时跳过未更新的文件)。开启前可 git update-index --test-untracked-cache 先验证系统支持
git maintenance 内置仓库优化命令,定期执行(如每天)让 add/fetch 更快、仓库更省磁盘

组合拳补充:

  • sparse checkout:只检出需要的子目录——生成文件、大目录不进工作目录,add/status 天然变快;
  • 只跟踪真正被修改的文件:仓库里躺着大量"从不被开发者修改"的生成文件,跟踪它们是纯浪费。

结合构建系统可知开发者正关注哪个组件,配合 sparse checkout,工作目录只保留一小部分文件——git status/git add 秒回。

三、git status 的内部机制

  1. 它执行两次 diff:HEAD↔暂存区、暂存区↔工作目录;
  2. 为什么这么快?两个原因——
    • 结构:提交中的文件存为 tree 对象,索引是 tree 的扁平结构,所有文件都有预计算哈希,diff 实际是比较哈希;
    • 缓存:索引缓存了工作目录信息,命中缓存就不必再看工作目录文件。

补充知识:

  • git diff-index HEADgit diff HEAD 快——它只看元数据(时间戳)不比较内容;
  • git status 内部就复用了 diff 机制来报告跟踪状态。

四、动手练习三连

练习 1:首次提交(My First Commit)

目标:掌握 commit 全流程。

步骤:新建目录 → git init 建仓库 → 创建内容为 "hello commit" 的文件 → 提交 → 用命令验证提交已记录。

验证:git log --oneline(或 git show --stat HEAD)。

思考题:提交的收益是什么?还有别的方式验证提交吗?(答:提交是时间点快照,可追溯可回滚;git status 显示 clean、git cat-file -p HEAD 等均可验证。)

练习 2:创建分支(Time to Branch)

目标:理解分支的独立性。

步骤:准备一个至少含一次提交的仓库 → 创建分支 dev → 修改文件 → 新提交 → 验证该提交只在 dev 分支

验证:git log --oneline dev 有而 git log --oneline main 没有;git branch -v 查看指针位置。

思考题:分支为什么有用?举一个真实场景(答:并行开发互不干扰——一个团队同时做新功能与修 bug,各自在独立分支上提交,最后合并)。

练习 3:Squash 提交(Squashing Commits)

目标:把多个提交压成一个。

步骤:创建内容为 "Mario" 的文件并提交 → 改为 "Mario & Luigi" 再提交 → 验证有两个提交 → 把最近两个提交 squash 成一个。

验证:git log --oneline 只剩一个提交,内容为合并后的最终状态。

思考题:为什么要 squash?(答:合并前清理"草稿"历史,主干保持清晰有意义的提交粒度。)能 squash 超过 2 个吗?(答:能,git rebase -i HEAD~N 任意数量。)

小结

  • gitattributes:* text=auto 一键解决跨平台换行。
  • monorepo 提速:fsmonitor 持续监视、manyFiles 缓存 mtime、maintenance 定期优化、sparse checkout 只检出需要的。
  • status 之谜:两次 diff,但靠哈希比较+索引缓存保持快速。
  • 练习三连:commit(快照)/branch(并行)/squash(整理历史)。

下一节预告:Git 打底完成,进入运行环境——Linux 系统。


发布者: 作者: 灏天文库 转发
评论区 (0)
U