git进阶07_Git 高级技巧与故障排查

06 - Git 高级技巧与故障排查

本章目标:掌握企业实战中的高级 Git 技巧,能独立排查和解决各种 Git 故障。


一、git reflog --- 救命神器

这是 Git 最被低估的功能,关键时刻能救你的命。

bash 复制代码
# 查看所有操作记录(包括已经 reset 掉的 commit)
git reflog

# 输出示例:
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: feat: add login
# ghi9012 HEAD@{2}: commit: feat: add register
# jkl3456 HEAD@{3}: commit: feat: add dashboard

常见救命场景

bash 复制代码
# 场景1:误删了分支
git branch -D feature/important
# 没关系!
git reflog                    # 找到分支最后的 commit
git checkout -b feature/important abc1234  # 恢复

# 场景2:误执行了 git reset --hard
git reflog                    # 找到 reset 前的 commit
git reset --hard abc1234      # 恢复

# 场景3:push 后发现代码有问题
git reflog                    # 找到 push 前的 commit
git reset --hard abc1234      # 回退
git push --force-with-lease   # 强制推送(回退远程)

二、git reset 的三种模式

bash 复制代码
# ===== 模式对比 =====

# --soft:只撤销 commit,保留暂存区和工作区
git reset --soft HEAD~1
# 效果:commit 被撤销,改动仍在暂存区(绿色)

# --mixed(默认):撤销 commit + 暂存区,保留工作区
git reset HEAD~1
# 效果:commit 被撤销,改动在工作区(红色)

# --hard:全部撤销(危险!不可恢复)
git reset --hard HEAD~1
# 效果:commit、暂存区、工作区全部撤销
复制代码
                    --soft          --mixed         --hard
                  ┌──────────┐   ┌──────────┐   ┌──────────┐
暂存区(Staged)  │  保留 ✅  │   │  清空 ❌  │   │  清空 ❌  │
                  ├──────────┤   ├──────────┤   ├──────────┤
工作区(Working) │  保留 ✅  │   │  保留 ✅  │   │  清空 ❌  │
                  └──────────┘   └──────────┘   └──────────┘

使用场景

bash 复制代码
# 修改最近一次 commit 的内容
git add forgotten-file.js
git commit --amend --no-edit

# 或者
git add forgotten-file.js
git reset --soft HEAD~1
git commit -m "feat: add login (with forgotten file)"

# 撤销最近一次 commit(保留改动)
git reset HEAD~1

# 彻底回退到某个版本(危险操作,慎用)
git reset --hard v1.0.0

三、git revert --- 安全回滚

reset 不同,revert 会创建一个新的 commit 来撤销指定的 commit,不会改变历史

bash 复制代码
# 回滚最近一次 commit
git revert HEAD

# 回滚指定 commit
git revert abc1234

# 回滚多个 commit
git revert abc1234..def5678

# 回滚合并 commit(需要指定主线)
git revert -m 1 <merge-commit-hash>

reset vs revert 对比

复制代码
场景:已 push 到远程的 commit 有问题

git reset --hard HEAD~1
  ✅ 直接回退
  ❌ 改变了历史,其他人需要重新 clone
  ❌ 如果有其他人在基于你的代码开发,会造成灾难

git revert HEAD
  ✅ 创建新 commit 撤销,不改变历史
  ✅ 安全,其他人可以正常 pull
  ❌ 历史中会多一个 "revert" commit

企业规则:已 push 的代码用 revert,未 push 的代码用 reset。


四、git rebase 深入

4.1 rebase vs merge 的本质区别

复制代码
merge(合并):
  * merge commit
  |\
  | * feature commit 2
  | * feature commit 1
  |/
* develop commit

rebase(变基):
  * feature commit 2
  * feature commit 1
  * develop commit 2
  * develop commit 1

4.2 交互式 rebase(最强大的功能)

bash 复制代码
# 修改最近 5 次 commit
git rebase -i HEAD~5

# 编辑器显示:
pick abc1234 feat: add login form
pick def5678 feat: add login API
pick ghi9012 fix: fix typo in login
pick jkl3456 feat: add logout button
pick mno7890 fix: fix logout bug

# 命令说明:
# pick   = 保留这个 commit
# reword = 保留但修改 commit message
# edit   = 保留但修改内容
# squash = 合并到上一个 commit(保留 message)
# fixup  = 合并到上一个 commit(丢弃 message)
# drop   = 删除这个 commit

# 示例:把 fixup 合并到对应的 feat commit
pick abc1234 feat: add login form
pick def5678 feat: add login API
fixup ghi9012 fix: fix typo in login
pick jkl3456 feat: add logout button
fixup mno7890 fix: fix logout bug

4.3 rebase 的黄金法则

不要对公共分支(main/develop)执行 rebase!

不要对已经 push 到远程且别人正在使用的分支执行 rebase!

复制代码
为什么?
因为 rebase 会重写 commit hash,
如果别人基于旧的 commit 继续开发,
他们的代码和你的代码就会产生冲突。

五、git bisect --- 二分查找 Bug

bash 复制代码
# 启动二分查找
git bisect start

# 标记当前版本有 Bug
git bisect bad

# 标记一个已知好的版本
git bisect good v1.0.0

# Git 会自动 checkout 中间的 commit
# 测试后告诉 Git 好坏
git bisect good    # 这个版本没问题
git bisect bad     # 这个版本有问题

# 重复几次后,Git 会找到引入 Bug 的第一个 commit
# 结束后
git bisect reset

自动化 bisect

bash 复制代码
# 用脚本自动测试
git bisect start HEAD v1.0.0
git bisect run npm test

# Git 会自动运行 npm test,根据返回值判断好坏
# 0 = good, 非 0 = bad

六、git worktree --- 多分支并行开发

场景:你在开发功能 A,需要紧急修 Bug,但不想 stash 当前工作。

bash 复制代码
# 在另一个目录 checkout 另一个分支
git worktree add ../hotfix-branch hotfix/fix-bug

# 现在你有两个工作目录:
# 1. 原目录:feature/user-login(继续开发功能 A)
# 2. ../hotfix-branch:hotfix/fix-bug(修 Bug)

# 修完 Bug 后
cd ../hotfix-branch
git add .
git commit -m "fix: critical bug"
git push origin hotfix/fix-bug

# 删除 worktree
git worktree remove ../hotfix-branch

# 查看所有 worktree
git worktree list

七、git archive --- 导出代码快照

bash 复制代码
# 导出当前分支的代码(不包含 .git 目录)
git archive -o latest.zip HEAD

# 导出指定 tag
git archive -o v1.0.0.zip v1.0.0

# 导出指定目录
git archive -o src.zip HEAD src/

八、git clean --- 清理工作区

bash 复制代码
# 查看哪些未跟踪文件会被删除(dry run)
git clean -fd --dry-run

# 删除未跟踪的文件和目录
git clean -fd

# 删除被 .gitignore 忽略的文件
git clean -fdx

# 删除所有未跟踪的文件(危险!)
git clean -fdX

九、故障排查手册

9.1 "我的代码去哪了?"

bash 复制代码
# 查看所有操作记录
git reflog

# 查看 HEAD 指向
git log -1

# 查看分支图
git log --oneline --graph --all

# 查看某个 commit 的详细信息
git show abc1234

9.2 "我误删了文件/分支"

bash 复制代码
# 恢复删除的文件
git checkout HEAD -- <file>

# 或者
git restore <file>

# 恢复删除的分支
git reflog                          # 找到最后的 commit
git checkout -b <branch-name> <commit-hash>

9.3 "我 push 了错误的代码"

bash 复制代码
# 方案1:撤回 push(需要 force push,危险)
git reset --hard HEAD~1
git push --force-with-lease

# 方案2:revert(安全,推荐)
git revert HEAD
git push

9.4 "rebase 冲突太多了"

bash 复制代码
# 放弃本次 rebase
git rebase --abort

# 或者用 merge 代替
git merge origin/develop

9.5 "git pull 有冲突"

bash 复制代码
# 方案1:先 rebase 再 pull
git pull --rebase origin main

# 方案2:先 stash 再 pull
git stash
git pull origin main
git stash pop

# 方案3:放弃本地修改
git reset --hard origin/main

9.6 "detached HEAD 是什么?"

bash 复制代码
# 你 checkout 了一个 commit 而不是分支
git checkout abc1234
# 提示:You are in 'detached HEAD' state.

# 解决:创建一个新分支
git checkout -b temp-branch

# 或者回到之前的分支
git checkout main

9.7 "大文件不小心提交了"

bash 复制代码
# 从 Git 历史中彻底删除大文件
# 安装 git-filter-repo
pip install git-filter-repo

# 删除指定文件的所有历史
git filter-repo --invert-paths --path large-file.zip

# 或者用 BFG Repo-Cleaner
java -jar bfg.jar --strip-blobs-bigger-than 10M repo.git

十、Git 配置速查

bash 复制代码
# ===== 查看配置 =====
git config --list              # 所有配置
git config --global --list     # 全局配置
git config --local --list      # 仓库配置

# ===== 设置配置 =====
git config --global <key> <value>    # 全局
git config --local <key> <value>     # 仓库级

# ===== 删除配置 =====
git config --global --unset <key>
git config --local --unset <key>

# ===== 常用配置项 =====
core.autocrlf          # 换行符处理
core.editor            # 默认编辑器
pull.rebase            # pull 时是否 rebase
push.default           # push 默认行为
init.defaultBranch     # 默认分支名

十一、Git 别名配置

bash 复制代码
# 常用别名
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.cm commit
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.last "log -1 --stat"
git config --global alias.unstage "reset HEAD --"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.wip "!git add -A && git commit -m 'WIP: work in progress'"
git config --global alias.undo "reset --soft HEAD~1"

十二、练习清单

学完本章,请完成以下操作:

  • git reflog 找回一个被 git reset --hard 删除的 commit
  • git revert 回滚一个已 push 的 commit
  • git rebase -i 把 3 个 commit 压缩成 1 个
  • git bisect 定位一个引入 Bug 的 commit
  • git worktree 同时在两个分支上工作
  • 制造一个 "detached HEAD" 并安全恢复

上一章05-企业级CI-CD与代码质量

下一章07-完整实战场景演练