19. 删了分支找不回?Git 常见问题排查与修复指南
「Git」系列已发布: 00. 改崩代码不敢回退?Git 版本控制 3 分钟救你狗命 | 01. Git 装完不会配?Windows/macOS/Linux 三端配置一次到位 | 02. Git 配置总踩坑?全局/仓库/SSH 密钥一次搞懂 | 03. add/commit/push 别再死记:Git 工作流核心概念实操 | 04. Git 分支管理:5 步彻底搞懂 branch 与 merge | 05. clone/fetch/pull/push 分不清?Git 远程协作实战 | 06. 给版本打上永久印记:Git 标签管理与发布实战 | 07. 切分支怕丢改动?Git stash 暂存恢复保护现场 | 08. rebase 不是 merge 的替代品:Git 故事线重构进阶 | 09. Git 日志与调试:log/blame/diff 让历史无所遁形 | 10. 提交代码自动检查:Git Hooks 实战,质量不再靠人工 | 11. 多仓库依赖怎么管?Git 子模块统一版本一键更新 | 12. GitFlow vs GitHub Flow vs 主干:团队工作流 3 选 1 | 13. 仓库越来越大?Git LFS 让图片视频不再撑爆仓库 | 14. 合并冲突不是噩梦:Git 合并策略与冲突解决 | 15. 常用命令记不住?Git 别名让操作变成快捷键 | 16. 仓库太大会卡顿?git gc + bfg 清理历史垃圾实战 | 17. 把密码提交进 Git?安全实践:密钥管理与审计日志 | 18. IDE 里的 Git 怎么用?VS Code/IntelliJ 集成效率翻倍 | 19. 删了分支找不回?Git 常见问题排查与修复指南(本文)
detached HEAD 是什么鬼?丢失的 commit 还能救吗?误删分支怎么找回?本文汇总 Git 高频故障与修复命令,遇事不慌。
Git 系列最后一篇。前面 18 篇把命令、原理、工作流都讲了一遍,但真正让人半夜冒冷汗的,往往是「完了,我好像把东西搞丢了」。这一篇不教新概念,只做一件事:把你最可能踩的坑列出来,告诉你怎么把损失找回来。建议先收藏,等真出事时再按图索骥。
一、提交相关
1.1 提交到了错误的分支
这大概是每个人都会经历一次的经典事故:本来想在 feature 上开发,结果脑子一热直接在 main 上写完了,还 commit 了。
两种救法,看你喜欢哪种风格:
方案一:cherry-pick + reset(适合已经提交、想挪走)
先开个 feature 分支把成果接住,再把 main 退回去:
git checkout -b feature/new-feature
git checkout main
git reset --hard HEAD~3 # 假设误提交了 3 个,main 退回这三个之前
reset --hard 看起来吓人,但只要没推到远程,它只是把指针往后挪,那 3 个提交还在 feature 分支上好好待着,丢不了。
方案二:rebase 后移动分支(更干净)
如果还没 commit 完,直接在 feature 分支上接着写、再把 main 拉回远程状态:
git branch feature/new-feature # 在当前位创建 feature 分支
git reset --hard origin/main # main 重置到和远程一致
1.1.1 改最近一次提交
刚 commit 完发现漏了个文件,或者提交信息打错字——别急着再 commit 一次去补,用 --amend 把这次提交改掉最干净:
# 补遗漏的文件(不新增提交,并入上一次)
git add forgotten-file.py
git commit --amend --no-edit
# 连提交信息一起改
git commit --amend -m "新的提交信息"
重点提醒:如果已经 push 上去了,再 --amend 就改写了历史,远程不会自动同步,必须:
git push --force-with-lease
注意是 --force-with-lease 不是 --force,区别下面 1.3.1 会讲,先记住这条保命命令。
1.1.2 改更早的提交
不是最近一次,是倒数第 3 个写错了?用交互式变基,把那一个标成 edit:
git rebase -i HEAD~3
# 编辑器里把目标那行的 pick 改成 edit
# 保存退出后,Git 会停在第一个 edit 的地方
git add modified-file.py
git commit --amend --no-edit
git rebase --continue
--continue 会一路跑完剩下的提交。中途想反悔?git rebase --abort 一键回到变基前的状态,放心试。
1.2 分支相关
1.2.1 撤销对分支的合并
把 feature 错合进了 main,心跳加速了吧。先深呼吸,没推之前一切好说。
# 方案二(没推送时最省事):直接回退一个提交
git reset --hard HEAD~1
如果已经推送了,别用 reset 硬抹(会把别人的历史也洗掉),用 revert 生成一次「反向提交」:
git revert -m 1 HEAD # -m 1 表示以 main 为基准方向撤销
revert 的好处是历史还在,团队其他人 pull 下来不会冲突。代价是:哪天你又想把那个 feature 合进来,得先 revert 掉这个 revert 提交,否则 Git 会以为「这东西已经被撤了」。
1.2.2 找回删除的分支
删了本地分支,发现里面还有没合并的宝贝?别慌,reflog 记得你每一次 HEAD 的移动,分支删了它还在。
git reflog
# 你会看到类似:
# abc1234 HEAD@{1}: commit: feat: 完成 feature-x
# def5678 HEAD@{2}: checkout: moving from feature-x to main
找到删之前那个提交哈希,原地起个新分支接住它:
git checkout -b recovered-feature def5678
关键认知:分支只是个指向提交的标签。标签撕了,下面的提交对象还在仓库里躺一段时间(默认 30 天),所以删分支≠丢代码,翻 reflog 基本都能捞回来。
1.2.3 分支重命名(含远程)
本地改个名很简单,麻烦的是远程那一份和同事的本地引用:
# 1. 本地改名
git branch -m old-branch-name new-branch-name
# 2. 推新分支、删远程旧的
git push origin new-branch-name
git push origin --delete old-branch-name
通知同事一句,让他们也清理一下:
git fetch --prune
git branch -m old-branch-name new-branch-name
git branch --unset-upstream
git branch -u origin/new-branch-name
1.3 远程相关
1.3.1 强制推送的正确姿势
永远别用 --force。 它不管远程有没有别人的新提交,二话不说覆盖上去,同事一下午的活可能就这么没了。
# 用这个替代 --force
git push --force-with-lease
--force-with-lease 的逻辑是:只有当远程分支和你上次拉取时完全一致才允许推。如果这期间别人推了新提交,它会拒绝,逼你先 pull 再推——这就是它保命的地方。把它设成默认也不过分:
git config --global alias.pushf "push --force-with-lease"
1.3.2 non-fast-forward 错误
git push 报 ! [rejected] main -> main (non-fast-forward),意思是远程有你本地没有的提交(多半是同事先推了)。这不是错误,是 Git 在保护你。
git fetch origin
git merge origin/main # 或者 git rebase origin/main
# 解决冲突后
git push origin main
merge 会多一个合并提交,rebase 让历史更线性好看,二选一,团队约定哪个就用哪个。
1.3.3 detached HEAD
git checkout <某个commit哈希> 或 git checkout <tag> 之后,Git 会提示你进入了 detached HEAD 状态。说人话就是:HEAD 现在直接指着某个提交,而不是某个分支。
这时你改了东西、commit 了,提交是存在的,但因为没有分支指着它,切走之后就找不到了(又得靠 reflog 捞,烦)。
# 想保留现在的修改,立刻建个分支接住
git checkout -b temp-branch # 老写法
# 或者 Git 2.23+ 更直白的:
git switch -c temp-branch
# 只是误入,想回到原来那个分支:
git switch -
记住:detached HEAD 本身不可怕,可怕的是你在上面写东西却不建分支就走人。
1.4 .gitignore 相关
1.4.1 已跟踪的文件加 .gitignore 没用
很多人踩过这个坑:明明写了 .gitignore,logs/app.log 还是一直出现在 git status 里。
原因很直白:.gitignore 只对「未跟踪」文件生效。这个文件早就被 Git 跟踪了,ignore 管不着它。要先把它的跟踪关系解除:
git rm --cached tracked-file.log
# --cached:只从 Git 索引移除,工作目录里的文件原样保留
git commit -m "chore: 停止跟踪 log 文件"
# 一整个目录都忘了?加 -r
git rm --cached -r logs/
1.4.2 .gitignore 不生效排查
规则写了却不生效,多半是这几个原因:路径相对仓库根写错了、glob 语法不对、或者文件尾随了空格导致匹配失败。
# 先看这文件到底有没有被跟踪
git ls-files | grep problematic-file
# 让 Git 告诉你这条规则是哪一行匹配的
git check-ignore -v problematic-file
# 输出类似:.gitignore:5:*.log problematic-file.log
# 意思是第 5 行的 *.log 命中了,照着这行去查拼写就行
1.5 性能相关
1.5.1 clone 太慢
遇到几个 G 的大仓库,clone 等到地老天荒。先浅克隆,要历史再说:
# 只要最近 1 次提交,秒下
git clone --depth 1 git@gitlab.com:team/large-repo.git
# 后来想要完整历史了
git fetch --unshallow
# 只要某个分支
git clone --single-branch --branch main git@gitlab.com:team/repo.git
# 仓库带 LFS 大文件、暂时用不到?跳过
GIT_LFS_SKIP_SMUDGE=1 git clone git@gitlab.com:team/repo.git
1.5.2 fetch 太慢
平时 git fetch 默认拉全部分支全量,慢得没道理。
# 只 fetch 当前分支
git fetch origin $(git rev-parse --abbrev-ref HEAD)
# 顺手做个日常保养,让仓库别越来越胖
git reflog expire --expire=30.days --all
git gc --auto
1.5.3 Git 卡顿或超时
大仓库推送卡死,先查是不是有大文件混进来了:
# 列出仓库里最大的 20 个对象
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {print $4, $3}' | sort -k2 -n -r | head -20
# 彻底压缩(会花点时间,但值得)
git gc --aggressive --prune=now
# 推送总超时?把 HTTP 缓冲区调大,比如 500MB
git config --global http.postBuffer 524288000
1.6 错误恢复
1.6.1 误删文件
rm 手滑删了文件别急着重写,Git 里大概率还有。
# 还没 commit 就 rm 了,从暂存区/最新提交恢复
git checkout -- deleted-file.txt
# 已经 commit 过、想恢复到某个历史版本
git log --oneline -- deleted-file.txt # 先找到那个提交
git checkout abc1234 -- deleted-file.txt
# 其实从最新提交恢复最常见:
git checkout HEAD -- deleted-file.txt
1.6.2 恢复已清除的 stash
git stash drop 甚至 git stash clear 了,以为全没了?fsck 能翻出那些「悬空」的提交对象:
# 列出所有不可达的提交,从中找 stash 的内容
git fsck --unreachable | grep commit | cut -d' ' -f3 | \
xargs git log --merges --no-walk --grep='WIP on'
# 找到对应的哈希后 apply 回来(不会删原 stash 对象,安全)
git stash apply <commit-hash>
1.6.3 撤销错误的 reset --hard
reset --hard 听起来像删库,但只要没 gc 清理,那条「被重置掉」的提交还在 reflog 里。
git reflog
# 找到重置之前那个重要提交
# abc1234 HEAD@{1}: commit: feat: 某个重要功能
git reset --hard abc1234
所以结论还是那句:只要没推远程、没手动 gc,Git 几乎什么都能捞回来,先 reflog 一下再说。
1.7 诊断命令速查
平时排查问题,这几个命令出镜率最高:
# 谁在什么时候改了这行(甩锅/查因神器)
git blame -L 100,120 src/main.py
git log -L 100,120:src/main.py # 这段代码的完整演进史
# 两个分支到底差在哪
git diff main..feature
git diff --stat main..feature # 只看文件级统计
# 二分法定位引入 bug 的提交,比肉眼快一百倍
git bisect start
git bisect bad HEAD # 当前这个有 bug
git bisect good v1.0.0 # 这个版本是好的
# Git 会自动切到中间提交,你测完标 good/bad,重复到找到为止
git bisect reset
# 看某次提交改了啥
git show abc1234
git diff abc1234~ abc1234
# 每人贡献统计(年终汇报用得上)
git shortlog -sn --all --no-merges
1.8 文章引用
二、系列文章 · Git 从入门到精通
本系列共 20 篇,建议从 00 开始顺序阅读。
|| 00 | 改崩代码不敢回退?Git 版本控制 3 分钟救你狗命 | 已发布 |
|| 01 | Git 装完不会配?Windows/macOS/Linux 三端配置一次到位 | 已发布 |
|| 02 | Git 配置总踩坑?全局/仓库/SSH 密钥一次搞懂 | 已发布 |
|| 03 | add/commit/push 别再死记:Git 工作流核心概念实操 | 已发布 |
|| 04 | Git 分支管理:5 步彻底搞懂 branch 与 merge | 已发布 |
|| 05 | clone/fetch/pull/push 分不清?Git 远程协作实战 | 已发布 |
|| 06 | 给版本打上永久印记:Git 标签管理与发布实战 | 已发布 |
|| 07 | 切分支怕丢改动?Git stash 暂存恢复保护现场 | 已发布 |
|| 08 | rebase 不是 merge 的替代品:Git 故事线重构进阶 | 已发布 |
|| 09 | Git 日志与调试:log/blame/diff 让历史无所遁形 | 已发布 |
|| 10 | 提交代码自动检查:Git Hooks 实战,质量不再靠人工 | 已发布 |
|| 11 | 多仓库依赖怎么管?Git 子模块统一版本一键更新 | 已发布 |
|| 12 | GitFlow vs GitHub Flow vs 主干:团队工作流 3 选 1 | 已发布 |
|| 13 | 仓库越来越大?Git LFS 让图片视频不再撑爆仓库 | 已发布 |
|| 14 | 合并冲突不是噩梦:Git 合并策略与冲突解决 | 已发布 |
|| 15 | 常用命令记不住?Git 别名让操作变成快捷键 | 已发布 |
|| 16 | 仓库太大会卡顿?git gc + bfg 清理历史垃圾实战 | 已发布 |
|| 17 | 把密码提交进 Git?安全实践:密钥管理与审计日志 | 已发布 |
|| 18 | IDE 里的 Git 怎么用?VS Code/IntelliJ 集成效率翻倍 | 待发布 |
|| 19 | 删了分支找不回?Git 常见问题排查与修复指南 | 待发布 |
#Git #版本控制 #DevOps
📌 本文首发于微信公众号 【运维知识点滴】——专注运维实战干货,微信搜索“运维知识点滴”或扫下方二维码关注,更新不迷路。
| 微信公众号【运维知识点滴】 | 微信小程序【A5单据合并&大试卷拆分转A4打印】 |
|---|---|
![]() |
![]() |
| 运维实战干货 · 关注追更 | Word 转 PDF · 试卷/发票打印神器 · 免费 |
💡 小程序【A5单据合并&大试卷拆分转A4打印】是干嘛的? 一个 Word 转 PDF 的打印神器,专治“文档版式和打印机对不上”:
- A3 试卷打不出来? 学校发的电子版试卷多是 A3,家用打印机只吃 A4——上传 Word 一键转换:可缩到一页 A4(页数不变),也可对半拆成两张 A4(1:1 原大、字更清晰),两种模式自选;
- 版式不乱:真实渲染引擎原样转换、绝不重排内容,转出的 PDF 和原 Word 排版一致,公式/表格/图片不跑版;
- 两张 A5 单据拼一张 A4:出租车票、火车票等报销凭证拼版后,一次打印、整齐粘贴;
- 隐私省心:无需注册,转换结果留存 5 天、最多下载 5 次即自动删除,不留任何历史记录;
- 微信扫码即用,免费、免安装,支持 doc / docx(≤50MB)。

