外观
11 · 清理、维护与高级主题
日常用不到,但遇到大仓库、子模块、误删对象时知道「有这扇门」即可。不展开成专题。
git gc / git fsck
git gc
作用: 打包松散对象、删除过期 reflog 和不可达对象。Git 在合适的时候会自己跑。
改动范围: 对象库压缩。可能让很久以前的 dangling commit 再也找不回。
bash
git gc不要这样用: 刚 reset --hard / stash clear 完立刻 gc --prune=now,等于亲手关掉还原窗口。
git fsck
作用: 检查对象库完整性,列出 dangling blob / commit(没人引用但仍在磁盘上)。
改动范围: 只读。
bash
git fsck --lost-found典型急救:曾经 add 过但从未 commit,后来 restore 丢掉了——blob 可能 dangling。lost-found 目录里能翻到文件碎片。见 急救手册。
git archive
作用: 打一份不含 .git 的源码包,用于发交付物。
bash
git archive --format=zip --output=demo-v1.2.0.zip v1.2.0不是备份仓库。备份历史请复制整个目录或用 git bundle。
git bundle
作用: 把指定提交打成一个文件,在没有网络或只能传文件时当远程用。
bash
git bundle create repo.bundle main
git clone repo.bundle demo浅克隆与部分克隆
仓库太大时:
bash
git clone --depth 1 <url> # 只要最近提交
git fetch --unshallow # 事后补全
git clone --filter=blob:none <url> # 部分克隆:先不拉文件内容,用时再取浅仓库上 rebase / bisect / blame 可能不准。当完整历史工具不好用时,先怀疑是不是 --depth。
sparse-checkout
只检出仓库的一部分目录,适合巨型 monorepo:
bash
git sparse-checkout init --cone
git sparse-checkout set apps/web不改变远程历史。切回全量:git sparse-checkout disable。
子模块 submodule(三板斧)
子模块是「主仓库里记录另一个仓库的某个 commit 指针」。
bash
git clone --recurse-submodules <url>
# 已经 clone 了:
git submodule update --init --recursive改子模块里的代码后:
- 在子模块目录里 commit + push。
- 回到主仓库,会看到子模块指针变化,再 commit 这个指针。
常见坑: 只改了子模块工作区,忘了在子模块里 commit,主仓库无法记录「脏」状态以外的东西。手改子模块目录却去主仓库 reset --hard,子模块未提交改动会丢。
删除子模块步骤容易漏文件,需要时查当时 Git 版本文档,不要只删目录。
Git LFS
大二进制(模型、视频、设计稿)不该直接进普通 Git。LFS 把文件换成指针,实体存在 LFS 服务器。
- 什么时候需要:单文件经常几十 MB,clone 变慢,历史爆炸。
- 已经把大文件 commit 进去:后续要用
git lfs migrate或git filter-repo改写历史,所有人必须配合重克隆。这是少数「真的可能要重新拉项目」的情况,且要团队公告。
改写整段历史(了解即可)
从历史里抹掉密钥、剥离大文件:
- 现在推荐:
git filter-repo(需单独安装) - 旧:
git filter-branch(慢、易用错)
做完必须 --force-with-lease 推所有分支和标签,每个协作者按公告重置本地。这不是个人急救手段。密钥仍要当作已泄露而轮换。
邮件补丁工作流
git format-patch / git am / git send-email 用于邮件列表贡献(Linux 内核等)。Web 托管 + PR 的团队用不到。
git notes
把额外说明挂到已有 commit 上而不改 SHA。很少用于应用开发。