Skip to content
Chapter 10

故障排查

仓库损坏、推送被拒、SSH 连接失败……遇到问题不要慌。本章教你系统化地诊断和修复 Git 中最常见的故障场景。

仓库损坏与恢复

.git 目录损坏了怎么办?

使用 git fsck(File System Consistency Check)检查仓库完整性,它会扫描所有对象并报告问题:

git fsck
# missing blob 3a2b1c0...
# dangling commit d4e5f6g...

git fsck 会列出 missing(丢失的对象)和 dangling(悬空的对象,即不可达但没有被引用的对象)。对于 minor 问题,可以尝试 git gc 自动修复。如果损坏严重,从远程仓库重新克隆是最彻底的恢复方式:

# 备份当前工作目录
cp -r my-project my-project.bak
# 重新克隆
git clone git@github.com:user/repo.git my-project-new
⚠ 危险操作提醒
如果 git fsck 报告大量 missing 对象且远程仓库可用,直接重新克隆比手动修复更安全。不要尝试手动编辑 .git/ 目录中的文件,这可能导致数据永久丢失。
分支指针丢失了怎么办?

如果不小心删除了分支或 reset 过头,分支指针丢失但提交对象仍然存在(在 GC 清理之前)。用 git reflog 找到之前的位置:

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~2
# e5f6g7h HEAD@{1}: commit: 重要功能完成
# i8j9k0l HEAD@{2}: commit: 修复登录 bug

找到目标提交后,用 git reset --hard 恢复:

git reset --hard e5f6g7h

如果是删除了分支,可以重新创建:

git branch recovered-branch e5f6g7h
✅ 成功恢复
git reflog 记录了 HEAD 的每一次移动,默认保留 90 天。只要提交还没被 GC 清理,几乎所有误操作都可以通过 reflog 找回。
仓库体积越来越大怎么办?

Git 仓库膨胀的常见原因是历史中存在大文件(二进制文件、数据集等)。处理方法:

1. 深度压缩:git gc --aggressive 会花更多时间优化压缩效果,适合大仓库的定期维护。

2. 清理大文件:使用 git filter-repo(推荐替代已废弃的 git filter-branch)从历史中彻底移除大文件:

# 安装 git-filter-repo
pip install git-filter-repo
# 从历史中移除 path/to/large-file.zip
git filter-repo --path path/to/large-file.zip --invert-paths

3. 打包松散对象:git repack -a -d 将松散对象打包成 pack 文件,-a 表示所有对象,-d 表示删除旧的 pack。

⚠ 危险操作提醒
git filter-repo 会重写整个历史,所有提交的 hash 都会改变。执行前确保团队成员知晓,并备份仓库。执行后所有人需要重新克隆。
故障排查练习
── 模拟场景:仓库出现异常,需要诊断和修复 ──
输入 help 查看可用命令,点击"提示"获取引导
$

推送与连接问题

推送被 rejected 但不确定原因?

推送被拒绝说明远程分支有你本地没有的新提交。分步排查:

# 1. 获取远程最新状态
git fetch origin

# 2. 查看本地领先远程多少提交
git log origin/main..HEAD --oneline

# 3. 查看远程领先本地多少提交
git log HEAD..origin/main --oneline

# 4. 合并远程变更后再推送
git pull --rebase origin main
git push origin main

git log A..B 语法表示"在 B 中但不在 A 中的提交",非常适合对比本地和远程的差异。

git gc 是什么?什么时候需要手动执行?

git gc(Garbage Collection,垃圾回收)执行以下操作:

  • 清理松散对象,将它们打包成 pack 文件
  • 压缩 pack 文件,优化存储空间
  • 删除不可达的对象(如过期的 reflog 条目)
  • 清理过时的远程跟踪分支

Git 通常在以下时机自动执行 GC:推送、合并、检出等操作触发时。手动使用场景:

# 普通压缩
git gc

# 深度压缩(更耗时但效果更好,适合仓库首次克隆后或大清理)
git gc --aggressive
遇到 "dirty working tree" 错误怎么办?

"dirty working tree" 表示你有未提交的修改,阻止了某些操作(如 merge、rebase、pull 等)。解决方法:

# 临时保存当前修改
git stash

# 执行需要的操作
git pull --rebase origin main

# 恢复之前保存的修改
git stash pop

也可以用 git stash list 查看所有暂存,git stash drop 丢弃不需要的暂存。

SSH 连接到 GitHub 失败怎么排查?

SSH 连接失败是最常见的远程操作问题。按以下步骤排查:

# 1. 测试 SSH 连接
ssh -T git@github.com

# 2. 查看已加载的密钥
ssh-add -l

# 3. 如果没有密钥,生成新的
ssh-keygen -t ed25519 -C "your-email@example.com"

# 4. 添加密钥到 ssh-agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# 5. 复制公钥,添加到 GitHub Settings → SSH Keys
cat ~/.ssh/id_ed25519.pub

常见原因:密钥未添加到 ssh-agent、公钥未添加到 GitHub 账户、~/.ssh/known_hosts 中缺少 GitHub 的指纹。

✅ 连接成功
当 ssh -T git@github.com 返回 Hi username! You've successfully authenticated 时,说明 SSH 配置正确,可以正常推送和拉取。
⚠ 危险操作提醒
如果重新生成 SSH 密钥,旧密钥将失效。确保将新公钥添加到 GitHub、GitLab 等所有使用该密钥的服务。切勿将私钥(id_ed25519,无 .pub 后缀)分享给任何人。
SSH 诊断练习
── 模拟场景:无法推送到 GitHub,排查 SSH 连接 ──
输入 help 查看可用命令,点击"提示"获取引导
$

课程总结

故障排查的核心思路是什么?

记住三个原则:

1. 先诊断再行动。用 git status、git log、git fsck 等命令了解当前状态,不要盲目操作。

2. 善用安全网。git reflog 是你的时光机,git stash 是你的暂存区,它们可以让你安全地回退。

3. 不确定就备份。在执行有风险的操作前,先 cp -r 备份整个仓库目录,给自己留一条退路。

🎉 恭喜!你已完成全部 10 章学习
从最基础的 git init 到高级的故障排查,你已经掌握了 Git 的核心工作流。回到 课程目录 随时回顾任何章节,继续在实践中巩固你的 Git 技能!