“糟了,我把测试分支的代码合并到生产主分支了!”
“刚才那个 Commit 里包含了一个致命的空指针异常,怎么撤回?”

作为后端开发者,日常敲代码的时间可能只有一半,另一半时间都在和 Git 斗智斗勇。Git 不仅是一个版本控制工具,更是一台可以挽救职业生涯的“时光机”。今天,咱们不聊简单的 pull 和 push,直接上生产环境最实用的三大“救火”指令。

一、吃下“后悔药”:Reset 与 Revert

当你把错误的代码推送到本地或远端仓库时,如何体面地撤回?

1. git reset(毁灭式回滚)
如果你只是在本地 Commit 了,还没推送到远端,或者你确信远端这个分支只有你一个人在用,你可以直接使用 reset

1
2
3
4
5
# 退回到上一个版本,且保留你在工作区的修改(最安全)
git reset --soft HEAD^

# 彻底退回上一个版本,工作区的修改全部丢弃(极其危险,慎用!)
git reset --hard HEAD^

2. git revert(体面式回滚)
如果错误的代码已经 Push 到了公共分支(比如 main),千万不要用 reset,这会导致同事的本地分支历史错乱。你应该用 revert
revert 的原理是生成一个新的 Commit,这个新 Commit 的内容正好把你要撤回的那个 Commit 抵消掉。

1
2
# 撤销指定 commit-id 的修改,并生成一条新的提交记录
git revert <commit-id>

这样不仅修正了 Bug,还保留了完整的历史痕迹,非常优雅。

二、告别面条式历史:Rebase (变基)

当你从 main 切出一个特性分支开发了三天,这三天里 main 分支已经被别人合入了十几条记录。此时如果你直接 git merge main,你的提交历史中会多出一条极其难看的交叉合并线。

想要保持一条直线的极简提交历史,你需要用到 rebase

1
2
# 在当前特性分支下执行变基
git rebase main

它的原理是:把你当前分支的提交先“暂存”起来,把 main 分支的最新代码拉过来垫在底下,然后再把你的提交一个个“重新播放”在最上面。
注意:解决 Rebase 冲突时需要极度小心,解决完后使用 git rebase --continue 继续。

三、精准打击:Cherry-Pick (摘樱桃)

经典场景:你在开发分支 A 上修复了 3 个 Bug,提交了 3 次。现在领导要求把其中第 2 个 Bug 的修复紧急上线到 release 分支,但不能包含另外两个还没测完的 Bug 代码。

这个时候,你既不能 Merge 也不能 Rebase,唯有 cherry-pick 能救命。

1
2
3
4
5
# 先切换到你要上线的 release 分支
git checkout release

# 把分支 A 上的那个特定修复的 commit 强行“摘”过来
git cherry-pick <bug2-commit-id>

就这一行命令,干脆利落,只把那一次提交的改动精准地融入当前分支。

总结

对于一个成熟的研发团队来说,写出能够跑通的代码只是及格线,能够熟练运用 Git 维护一个干净、可追溯、随时可回滚的代码仓库,才是高级工程师的必修课。