Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

当你手滑误删分支、合并冲突一地鸡毛、线上出现紧急 bug 需要回滚时,这篇文章可能救你一命。


引言

凌晨两点,我刚写完一个功能,正准备 push 到远程。手一抖,敲成了 git reset –hard HEAD~1。

还没 push 的代码,没了。

那一瞬间,冷汗直接下来了,心脏狂跳。这不夸张,我真的经历过这种时刻。

说实话,我之前只会 add、commit、push 三个命令。真遇到突发状况,直接慌了:合并冲突咋办?分支删错了能恢复吗?线上出 bug 怎么快速回滚?

Git 本身不难,难的是你不知道它有哪些”救命”技巧。

这篇文章整理了 4 个我最常遇到的”至暗时刻”,每个场景都有具体的解决方案。看完你就能从容应对大部分突发状况。

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图1: Git 进阶学习路线图


场景 1:合并冲突怎么办

你正在写功能,同事也改了同一个文件。git pull 一执行,Git 报错冲突了。

打开文件一看,满屏的 <<<<<<<、=======、>>>>>>>。

什么反应?我之前也犯过这个错,直接选”接受”,或者干脆复制粘贴,强行提交。

千万别这么干。这样处理很可能把同事的代码覆盖了,或者引入新的 bug。我之前就这么干过,结果导致了线上故障,教训深刻。

怎么正确处理

先备份(养成好习惯)

git stash backup "解决冲突前的备份"

打开冲突文件看一眼

你会看到类似这样的标记:

<<<<<<< HEAD
def calculate(a, b):
    return a + b
=======
def calculate(x, y):
    return x + y
>>>>>>> feature/new-function

HEAD 到 ======= 是你的代码,下面是同事的代码。

手动合并

理解两边的逻辑,自己决定怎么合并。列如上面这个例子,你要用 a+b 还是 x+y,或者换个新名字。

def calculate(a, b):
    return a + b

测试!测试!测试!

不要急着提交,先把测试跑一遍,确保没问题了再提交。

git add .
git commit -m "解决合并冲突:统一函数参数命名"

几个提议

  • ⚠️ 别盲目选”接受 theirs/ours”,可能覆盖代码
  • ⚠️ 解决完冲突必定要测试,否则容易出问题
  • 勤提交能减少冲突(每完成一个小功能就 commit)

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图2: 合并冲突解决流程


场景 2:误删分支/提交

你在清理本地分支,手一滑,git branch -D feature/important 敲下去了。

回车按完那一秒,你突然想起来:这个分支还有没合并的重大代码。

那一刻,真的是冷汗直流。

用 git reflog 挽救

Git 有个”黑匣子”叫 reflog,它记录了你所有的操作,包括删掉的分支和提交。

只要你在 Git 里操作过,它都记得。

恢复误删的分支

# 先查看操作记录,找到删除前的 commit ID
git reflog

# 你会看到类似这样的输出:
# a1b2c3d HEAD@{0}: commit: 新增功能
# e5f6g7h HEAD@{1}: branch: Deleted branch feature/important

# 重新创建分支
git checkout -b feature/important e5f6g7h

恢复误删的提交

# 找到误操作前的状态
git reflog

# 恢复到那个状态
git reset --hard HEAD@{n}  # n 是 reflog 里的编号

我的踩坑经历

2024年8月某天,我在清理本地分支,手滑执行了 git branch -D feature/payment-gateway。

回车按完的一瞬间,我想起来:这个分支还有支付网关的核心代码,两天的成果啊。

那一刻,心真的凉了。

还好当时旁边的同事看到了,跟我说:”用 git reflog 试试。”

我半信半疑地执行了命令,找到了删除前的 commit ID(a1b2c3d),然后重新创建分支。代码全部找回来了。

从那后来,每次删分支前,我都会先确认一下这个分支是不是已经合并了。这个习惯救了我至少3次。

几个提议

  • ⚠️ 删东西前先备份(git stash 或者新建个分支)
  • ⚠️ 用 git branch -d 而不是 -D(前者会检查,后者直接删)
  • 勤提交(即使出问题,损失也小)

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图3: git reflog 救命示例


场景 3:需要回滚版本

你的代码刚上线,测试发现了个严重 bug,需要紧急回滚到上一个版本。

这时候你面临两个选择:git reset 还是 git revert?

选错了,可能把整个团队的代码搞乱。

三个命令的区别

git reset:本地回滚用

git reset --hard HEAD~1  # 回退到上一个版本

⚠️ 注意:这个命令会改历史。如果你已经 push 到远程了,再用 reset,其他同事 pull 的时候会出问题。

git revert:远程回滚用(安全)

git revert <commit-id>  # 创建新提交,撤销指定提交的修改
git push

为什么安全:它不修改历史,而是创建一个新的提交。多人协作也不会影响别人。

git checkout:恢复单个文件

git checkout -- <文件名>  # 恢复文件到最后一次提交的状态

怎么选?

需要回滚
├─ 已经 push 到远程了?
│  ├─ 是 → 用 git revert(安全)
│  └─ 否 → 用 git reset(快速)
└─ 只想恢复单个文件?
   └─ 用 git checkout

几个提议

  • ⚠️ 已推送的提交别用 reset,用 revert
  • ⚠️ force push 很危险,多人协作时千万别用
  • 回滚前先备份(git stash 或新建分支)

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图4: 三个回滚命令对比


场景 4:追踪 bug 来源

代码出了 bug,但你不知道是哪个提交引入的。

传统方法是逐个看提交记录,慢得要命。

实则 Git 有两个强劲的工具:git blame 和 git bisect。

git blame:追溯代码

这个命令能显示每一行代码是谁、在哪个提交里修改的。

什么时候用

  • 找 bug 是哪个提交引入的
  • 看某段代码的修改历史
  • Code review 时查看上下文

怎么用

git blame app.js

# 输出示例:
# a1b2c3d5 (张三 2024-01-15 10:30:20 +0800 15) function calculate() {
# e5f6g7h9 (李四 2024-01-16 14:20:15 +0800 16)     return a + b;

# 只看第 10-20 行
git blame -L 10,20 app.js

git bisect:二分查找 bug

这个命令用二分查找快速定位引入 bug 的提交,效率极高。

原理:每次缩小一半范围,很快就能找到问题。

怎么用

# 开始查找
git bisect start

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

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

# Git 会自动切换到中间版本,你测试后标记
git bisect good  # 或 git bisect bad

# 重复测试,直到找到问题提交
git bisect good  # 或 git bisect bad

# 结束查找
git bisect reset

实战案例

2024年11月,我们的订单系统出了个 bug:有些用户的订单状态会自动从”已支付”变成”待支付”。

这问题很严重,但我们不知道是哪个提交引入的。我当时想,逐个排查提交记录,至少得看 200 多个提交,估计得花 2 小时。

后来我想起了 git bisect。

我标记当前版本为 bad,v1.0.0 为 good(一个月前的版本,肯定没问题)。

Git 自动切换到中间版本,我测试后发现bug还在,标记为 bad。它又切换到更早的版本,我测试后标记为 good。

重复了5次,就精准定位到了问题提交:是一个并发处理的修改导致的。

全程只花了15分钟。

说实话,从那后来我就迷上了 git bisect,效率提升真的明显。

几个提议

  • ⚠️ bisect 需要有明确的好/坏版本
  • ⚠️ 测试时必定要准确判断,不然会走弯路
  • 配合 blame 用,定位更快

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图5: git blame 和 git bisect 调试演示


速查表

常见问题快速决策:

问题场景

推荐方案

命令速查

合并冲突

手动编辑 + git add

git add → git commit

误删分支

git reflog 恢复

git reflog → git checkout -b

本地回滚

git reset

git reset –hard HEAD~1

远程回滚

git revert

git revert <commit-id>

追溯代码

git blame

git blame filename

查找 bug

git bisect

git bisect start → git bisect good/bad

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图6: Git 救命命令速查表


总结

回顾一下

  • 合并冲突:手动解决,别暴力合并,解决完必定测试
  • 误删恢复:git reflog 是后悔药,记录了所有操作
  • 版本回滚:本地用 reset,远程用 revert
  • 追踪 bug:blame 看历史,bisect 快定位

几个好习惯

  • 勤提交,小批量提交(出问题损失也小)
  • 删东西前先备份
  • push 前先测试
  • 危险操作(reset –hard、branch -D)前确认一下

学习资源

  • Git 官方文档
  • Pro Git 电子书(在线免费)
  • GitHub Git Guide

这些技巧你不会每天都用,但需要的时候能救命。

提议收藏这篇文章,以备不时之需。

Git 救命锦囊:90% 开发者都会遇到的 4 个至暗时刻

图7: Git 最佳实践检查清单

© 版权声明

相关文章

暂无评论

none
暂无评论...