深夜,客户突然反馈线上的某个核心功能挂了,打开 Git 分支记录一看,居然有人把错误的代码合进了主分支,甚至更糟糕的是——它已经被部署到生产环境。

这种时候,git revert 已经不够用了。你需要的是 Git 的**”救火三件套”**:Reset、Cherry-Pick 以及进阶的 Rebase。

Reflog:找回丢失的一切

在进行任何危险的 Git 操作之前,先牢记一个保命指令:git reflog

Git 的 reflog 记录了你在这个仓库中做过的所有 HEAD 移动操作——包括那些已经被删除的分支、已经被 reset 掉的提交。只要操作发生在 30 天内(默认),reflog 就能帮你找回来。

1
2
3
4
5
git reflog
# 输出示例:
# abc1234 HEAD@{0}: commit: fix login bug
# def5678 HEAD@{1}: merge feature/payment: Merge made by ort strategy
# ghi9012 HEAD@{2}: checkout: moving from main to feature/payment

场景 1: 不小心 git reset --hard 回退了 3 个提交。

1
git reset --hard HEAD@{1}   # 回到 reset 之前的状态

场景 2: 误删了一个分支。

1
git branch feature/resurrected ghi9012   # 从 reflog 中找到 hash 重建分支

Cherry-Pick:只摘”樱桃”

git merge 会把整个分支的所有改动一次性倒进来。但很多时候,你只需要另一个分支上的某一个特定提交。

1
2
# 假设 main 线上崩了,修好 Bug 的代码在 hotfix/login-bug 分支
git cherry-pick hotfix/login-bug

更精细的操作——连续摘取多个提交:

1
2
git cherry-pick commitA..commitD   # 从 A 之后到 D 的所有提交(不含 A)
git cherry-pick commitA commitC commitF # 逐个指定

冲突处理:

1
2
3
git add .
git cherry-pick --continue # 解决冲突后继续
git cherry-pick --abort # 发现摘错了,果断放弃

Reset 三模式详解

模式 效果 适用场景
--soft 回退 HEAD,保留暂存区和工作区 把多个 commit 合并成一个
--mixed(默认) 回退 HEAD 和暂存区,保留工作区 撤销 add 但保留写的代码
--hard 回退一切 彻底丢弃脏代码
1
2
3
4
5
6
7
8
9
# 合并最近 5 个零散的 WIP 提交为一个
git reset --soft HEAD~5
git commit -m "feat: 实现支付回调的完整幂等性处理"

# 撤销最后一次 git add
git reset HEAD~1

# 彻底丢弃本地所有改动(危险!先确认)
git reset --hard origin/main

交互式 Rebase:提交历史整理

当你开发了一个功能,本地有 15 个 “fix typo”、”WIP”、”test again” 之类的提交,直接推到远程太不专业了。交互式 Rebase 让你可以像编辑文档一样编辑提交历史:

1
git rebase -i HEAD~15

编辑器会打开一个列表,每个提交前面有一个操作关键字:

  • pick:保留这个提交
  • squash:合并到上一个提交(保留 commit message)
  • fixup:合并到上一个提交(丢弃 commit message)
  • drop:删除这个提交
  • reword:修改 commit message

将中间 14 个提交的 pick 改为 fixup,只留第一个 pick,最终会得到一个干净优雅的提交历史。

Git Bisect:二分法定位 Bug

当你不确定 Bug 是哪个提交引入的,Git Bisect 用二分查找法自动帮你定位:

1
2
3
4
5
6
7
git bisect start
git bisect bad HEAD # 当前版本有 Bug
git bisect good v1.2.0 # v1.2.0 是好的
# Git 自动检出中间版本,你测试后告诉它:
git bisect good # 或 git bisect bad
# 重复几次后,Git 精确指出元凶提交
git bisect reset # 结束二分查找

这个功能在大型项目中极其有用——当 commit 数量成百上千时,手动逐个排查几乎不可能,Bisect 能在 log2(N) 步内锁定问题。

总结

Git 远不止 addcommitpush。Reflog 是你的后悔药,Cherry-Pick 是你的手术刀,Reset 是你的时光机,Rebase 是你的史书修撰官。掌握这些命令,你就是团队里那个能”徒手接锅并优雅化解”的 Git 宗师。