第23章:Git 故障排查 —— 当事情搞砸时
第23章:Git 故障排查 —— 当事情搞砸时
Git 用久了,总会遇到各种奇怪的问题。这一章,我们准备了一个"急救包",帮你解决最常见的 Git 故障。记住:冷静,Git 总有办法!
23.1 git fsck:检查仓库完整性
场景:Git 行为异常,怀疑仓库损坏。
你的心情:😰 → 🤔 → 💡 → ✅
“Git 突然抽风了,提交失败,提示一些看不懂的错误…是不是仓库坏了?”
什么是 git fsck?
git fsck(File System Check)是 Git 的"体检医生",它会检查 Git 对象数据库的完整性,找出损坏或丢失的对象。
1
2
3
4
5
6
7
8
| # 基础检查
git fsck
# 详细输出
git fsck --verbose
# 显示所有对象(包括不可达的)
git fsck --unreachable --no-reflogs
|
常见输出解读
1
2
3
4
5
6
7
8
9
10
11
| # 悬空 blob(正常)
dangling blob abc1234...
# 含义:有文件内容没有被任何提交引用
# 悬空 commit(需要注意)
dangling commit def5678...
# 含义:有提交没有被任何分支引用,可以用 reflog 找回
# 丢失的对象(严重!)
missing tree 7890abc...
# 含义:Git 找不到这个对象了,需要重新克隆
|
修复损坏的仓库
1
2
3
4
5
6
7
8
| # 方法1:从远程重新克隆(最简单)
cd ..
mv my-project my-project-corrupted
git clone https://github.com/user/repo.git my-project
# 方法2:使用 git reflog 恢复
git reflog
git reset --hard HEAD@{1}
|
幽默一刻
你:“Git 报错了,说 missing tree!”
Git:“别担心,我只是找不到一个对象。”
你:“那怎么办?”
Git:“重新克隆吧,从远程下载一个新的我。”
记住:git fsck 是 Git 的"体检医生"——定期体检,早发现早治疗!
23.2 修复损坏的仓库:从绝望中恢复
场景:.git 目录损坏,Git 完全无法工作。
你的心情:😱 → 😰 → 🤔 → 💪 → ✅
“完了完了,.git 目录好像坏了,所有 Git 命令都报错!”
冷静!代码很可能还在!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 检查工作区文件
ls src/
# 文件都在!太好了!
# 重新克隆仓库
git clone https://github.com/user/repo.git my-project-new
# 复制工作区的更改
cp my-project-backup/src/modified-file.js my-project-new/src/
# 提交更改
cd my-project-new
git add .
git commit -m "restore: 从损坏仓库恢复更改"
|
幽默一刻
你:".git 目录坏了,我完了!"
Git:“冷静,你的代码文件还在吗?”
你:“在!”
Git:“那就好,重新 clone,复制文件,提交,搞定。”
记住:仓库损坏不是世界末日——代码在工作区,远程有备份,总有办法恢复!
23.3 detached HEAD 状态:怎么办?
场景:checkout 了一个提交,现在 HEAD 是 detached 状态。
你的心情:😰 → 🤔 → 💡 → ✅
“我 checkout 了一个旧的提交,现在 Git 提示 ‘detached HEAD’,这是什么鬼?”
什么是 detached HEAD?
detached HEAD 是指 HEAD 直接指向一个提交,而不是指向一个分支。
1
2
3
4
5
6
7
8
9
| # 查看当前状态
git status
# HEAD detached at abc1234
# 创建新分支保存当前状态
git checkout -b new-feature
# 或者回到原来的分支
git checkout main
|
幽默一刻
你:“HEAD detached 了,怎么办?”
Git:“别担心,只是 HEAD 没有依附分支。”
你:“那我的代码呢?”
Git:“代码安全,但如果你切换分支,这些代码可能就’飘’了。”
记住:detached HEAD 不是错误——它是 Git 的"观景台",看完记得回到分支上!
23.4 合并冲突无法解决:终极方案
场景:冲突太复杂,无法解决。
1
2
3
4
5
6
7
8
9
10
11
12
| # 方法1:放弃合并
git merge --abort
# 方法2:使用合并工具
git mergetool
# 方法3:手动选择一方
git checkout --ours file.txt # 保留当前分支
git checkout --theirs file.txt # 保留合并分支
# 方法4:重置到合并前
git reset --hard HEAD
|
幽默一刻
你:“冲突太复杂了,我解决不了!”
Git:“那就放弃吧,merge –abort,世界恢复平静。”
你:“那我的工作呢?”
Git:“重新来过,有时候撤退是最明智的选择。”
记住:合并冲突不是战斗——有时候放弃合并,重新规划,反而是最高效的选择!
23.5 推送被拒绝的各种原因
场景:git push 被拒绝。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 原因1:非快进推送
git push origin feature
# ! [rejected] non-fast-forward
# 解决:先拉取再推送
git pull origin feature
git push origin feature
# 原因2:权限不足
git push origin main
# ! [remote rejected] main -> main (protected branch)
# 解决:使用 PR/MR 合并
# 原因3:远程有更新
git fetch origin
git rebase origin/main
git push origin main
|
幽默一刻
你:“推送被拒绝了!”
Git:“远程有更新,你先拉取一下。”
你:“为什么?”
Git:“因为世界在变,你也要跟着变。”
记住:推送被拒绝不是失败——是 Git 在保护你,避免覆盖他人的工作!
23.6 权限问题排查:SSH、Token、权限
场景:无法推送,提示权限错误。
1
2
3
4
5
6
7
8
| # 检查 SSH 连接
ssh -T git@github.com
# HTTPS 改为 SSH
git remote set-url origin git@github.com:user/repo.git
# 更新 Token
git remote set-url origin https://TOKEN@github.com/user/repo.git
|
幽默一刻
你:“我没有权限推送!”
Git:“检查一下你的 SSH 密钥。”
你:“密钥是什么?”
Git:“就是你的’身份证’,证明你是你。”
记住:权限问题是"门卫"问题——要么证明你是谁,要么找有权限的人!
23.7 认证失败:HTTPS 凭据问题
场景:提示输入用户名密码,或者认证失败。
1
2
3
4
5
6
7
8
| # 清除凭据缓存
git config --global --unset credential.helper
# Windows
git credential-manager delete https://github.com
# macOS
git credential-osxkeychain erase host=github.com protocol=https
|
幽默一刻
你:“Git 一直问我要密码!”
Git:“因为我忘了你是谁。”
你:“那怎么办?”
Git:“重新告诉我,我会记住的。”
记住:认证失败是"失忆"问题——重新告诉 Git 你是谁,它会记住的!
23.8 性能优化:大仓库加速技巧
场景:仓库太大,操作很慢。
1
2
3
4
5
6
7
8
9
10
11
12
| # 1. 浅克隆
git clone --depth 1 https://github.com/large/repo.git
# 2. 单分支克隆
git clone --single-branch https://github.com/large/repo.git
# 3. 稀疏检出
git sparse-checkout init --cone
git sparse-checkout set src/
# 4. 定期 gc
git gc --aggressive
|
幽默一刻
你:“克隆要 10 分钟,太慢了!”
Git:“试试浅克隆,只下载最新版本。”
你:“为什么这么快?”
Git:“因为你不需要 10 年前的代码。”
记住:大仓库需要"瘦身"——只取你需要的,忽略你不需要的!
23.9 仓库瘦身:清理历史大文件
场景:仓库太大,需要清理历史中的大文件。
1
2
3
4
| # 使用 git-filter-repo
pip install git-filter-repo
git filter-repo --strip-blobs-bigger-than 10M
git push origin --force --all
|
幽默一刻
你:“仓库 1GB 了,怎么办?”
Git:“你提交了太多大文件。”
你:“但我已经删除了!”
Git:“历史里还有,用 filter-repo 清理。”
记住:仓库瘦身是"减肥"——不仅要少吃,还要运动(清理历史)!
23.10 找回丢失的提交:git reflog 进阶用法
场景:误删了分支,或者 reset 了重要的提交。
1
2
3
4
5
6
7
8
| # 查看 reflog
git reflog
# 恢复删除的分支
git checkout -b recovered-branch HEAD@{5}
# 恢复 reset 前的状态
git reset --hard HEAD@{1}
|
幽默一刻
你:“我误删了分支!”
Git:“淡定,reflog 里有记录。”
你:“找到了!你是我的救命恩人!”
Git:“我是你的时光机,记得定期备份。”
记住:reflog 是 Git 的"时光机"——几乎所有操作都能找回,只要你记得用它!
23.11 本章小结:冷静,Git 总有办法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| ## 故障排查 checklist
- [ ] 保持冷静,不要 panic
- [ ] 使用 git status 查看状态
- [ ] 使用 git reflog 找回丢失的提交
- [ ] 使用 git fsck 检查仓库完整性
- [ ] 使用 --abort 取消当前操作
- [ ] 从远程重新克隆(最后手段)
- [ ] 定期备份重要仓库
## 黄金法则
1. 不要删除 .git 目录
2. 不要 force push 主分支
3. 定期 push 到远程
4. 使用 reflog 作为时光机
5. 冷静,Git 总有办法
|
冷静,Git 总有办法! 🚑✨
第23章完