🧓 老程序员的 Git 避坑手册:这 10 个命令,我当年要是早知道就好了
阅读时间:约 10 分钟
适合人群:Git 新手、被 Git 搞崩过代码的倒霉蛋、以及正在用鼠标点 SourceTree 的懒人
作者心情:一边敲键盘,一边想起被git push --force支配的恐惧
前言:我是如何在一个周五下午,把整个团队的代码库搞成一坨🌀的
那是 2015 年的一个下午,我信心满满地执行了一条命令:
git push origin main --force
然后,安静了。
群里安静了。
老板的消息来了:"小李,你刚才干嘛了?"
从那一天起,我发誓要把 Git 学明白。
这篇文章,就是我用无数次翻车经历换来的 10 个 Git 硬核技巧。不是"Hello Git"教程,是真正能救命的那种。
一、git reflog:后悔药,真的有
场景:你执行了 git reset --hard,整个分支的提交全没了,人也傻了。
很多新手以为这下完了,开始在脑海中演练离职流程。
但其实 Git 偷偷记了本:
git reflog
输出大概长这样:
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
d4e5f6g HEAD@{1}: commit: 修复了登录bug
h7i8j9k HEAD@{2}: commit: 加了个功能(虽然不知道有没有用)
找到你想恢复的那个 hash,然后:
git checkout -b 救命分支 d4e5f6g
💡 老鸟提醒:
reflog默认保留 90 天记录。所以别拖太久,90 天后真的凉凉。
二、git stash:上厕所前先藏好代码
场景:正写着代码,产品经理突然冲进来喊:"线上有个紧急 bug!!!"
你的代码写到一半,既不能提交(烂摊子),又不能不管(要切分支)。
新手做法:删代码 → 切分支 → 修 bug → 再把代码手打回来。(痛苦面具.jpg)
老司机做法:
git stash # 把现在的烂摊子藏起来
git checkout fix/urgent-bug
# ... 修 bug,提交,部署,被夸 ...
git checkout feature/my-work
git stash pop # 把烂摊子翻出来继续干
还能给 stash 起名字,方便多个"烂摊子"管理:
git stash save "登录页面写到一半,别删!"
git stash list # 查看所有藏起来的代码
💡 老鸟提醒:
stash pop和stash apply的区别——前者用完就扔,后者用完还留着。我一般用pop,极简主义。
三、git commit --amend:打完补丁再发车
场景:刚 git commit 完,发现 commit message 写的是 "asdfjkl;",或者少提交了一个文件。
正常操作是再提一个 commit,然后 log 里就出现了这样的记录:
fix bug
fix bug again
fix bug for real this time
ok now it's really fixed
why is this still broken
优雅操作:
# 漏了一个文件
git add 忘记的文件.js
git commit --amend --no-edit # 悄悄塞进上一个 commit,什么都没发生
# commit message 写错了
git commit --amend -m "feat: 完成用户登录功能"
⚠️ 重要警告:
amend会改写历史。如果这个 commit 已经 push 到远端了,你再 amend 再 force push,你的同事会想打人。这是经验之谈,不多说。
四、交互式 git rebase:整容手术,让 commit 好看起来
场景:你开发一个功能写了 20 个 commit,全是这种:
add file
modify
debug
debug again
wtf
ok fixed
typo
forgot semicolon
上 PR 之前,你总不能把这堆垃圾推给 reviewer 看吧?
用交互式 rebase 整容:
git rebase -i HEAD~8 # 最近 8 个 commit 进手术室
会弹出一个编辑器,你可以:
| 指令 | 作用 |
|---|---|
pick | 保留这个 commit |
squash / s | 和上一个 commit 合并 |
reword / r | 修改 commit message |
drop / d | 直接删掉这个 commit |
把那堆 debug/typo 全 squash 掉,最后变成一个干净的 commit,reviewer 看了直呼内行。
💡 老鸟提醒:rebase 会改写历史,所以只对本地分支或未 push 的分支用。在已经 push 的公共分支上 rebase?你会成为团队公敌。
五、git bisect:二分法排查 bug,比你用 console.log 聪明多了
场景:你打开项目,发现某个功能挂了。但你不知道是哪个 commit 搞坏的,距上次正常运行已经过去了 200 个提交...
新手做法:从头看每个 commit... 然后通宵...
老鸟做法:让 Git 自己排查。
git bisect start
git bisect bad # 当前版本是坏的
git bisect good v2.0.0 # 这个版本是好的
Git 会自动帮你二分,每次 checkout 到中间那个 commit,你只需要回答"好" 还是 "坏":
git bisect good # 这个版本没问题
git bisect bad # 这个版本有问题
几轮之后,Git 直接告诉你:"就是这个 commit 搞的鬼。"
💡 还能配合脚本全自动化,连"好坏"都不用你手判断,Git 自己跑测试。这才是真·懒人操作。
六、.gitignore 写早不写晚,写晚哭断肠
这不是命令技巧,这是血的教训。
新手常见的神操作:
- 把
node_modules(500MB)提交上去了 - 把含密码的
.env文件推到 GitHub 了 - 把整个
.idea文件夹(JetBrains 配置)污染了团队仓库
标准做法:项目第一天就建好 .gitignore。
推荐直接用生成工具:gitignore.io,选你的技术栈,一键生成。
已经误提交的文件,补救方法:
# 从 Git 追踪中移除,但本地文件保留
git rm --cached 误提交的文件.env
echo "*.env" >> .gitignore
git commit -m "chore: 移除敏感文件,从今天起好好做人"
⚠️ 但是:如果
.env已经 push 到公共仓库了,立刻去改密码!!git rm只是让文件消失在当前,历史记录里还查得到。想彻底抹掉,需要git filter-branch或BFG Repo Cleaner,那是另一个故事了。
七、git cherry-pick:只摘你想要的那朵花
场景:同事在 feature 分支上修了一个你急需的 bug,但他的分支乱得一塌糊涂,你不想合并整个分支,只想要那一个 commit。
git cherry-pick a1b2c3d # 只把这个 commit 摘到当前分支
也可以一次摘一段:
git cherry-pick a1b2c3d..f6g7h8i # 摘从 a 到 f 之间的所有 commit
💡 使用场景:hotfix 要同时上多个版本分支时,cherry-pick 比手动改代码优雅 100 倍。
八、git log 的正确打开方式
你现在用的 git log 可能长这样(一坨文字):
commit a1b2c3d4e5f6...
Author: 张三 <zhangsan@example.com>
Date: Mon Apr 7 10:23:11 2026 +0800
修改了一些东西
看一屏只能看到 3 条,效率堪比 IE6。
换成这个:
git log --oneline --graph --decorate --all
输出变成:
* a1b2c3d (HEAD -> main) feat: 完成支付模块
* d4e5f6g fix: 修复金额计算错误
| * h7i8j9k (feature/refactor) refactor: 重构数据层
|/
* j0k1l2m chore: 更新依赖
直观、好看、一眼看清分支结构。
嫌每次打太长?加个别名一劳永逸:
git config --global alias.lg "log --oneline --graph --decorate --all"
# 以后直接用:
git lg
九、用好 git diff,code review 不再瞎眼
很多人 git diff 只用来看改了什么,其实它能做更多:
git diff HEAD~3 # 和 3 个 commit 前比
git diff main..feature # 两个分支之间的差异
git diff --stat # 只看改了哪些文件,不看具体内容(省眼睛)
git diff --word-diff # 单词级别的 diff,改了哪个词一目了然
--word-diff 特别适合看文档或配置文件的改动,比行级 diff 精准多了。
十、git hook:让机器替你把关,别指望人
场景:每次 push 之前都要手动跑 lint、跑测试,有时候忘了,有时候懒了,然后 CI 挂了,被 review 打回来,很丢人。
解决方案:用 pre-commit hook,push 之前自动检查。
在项目根目录 .git/hooks/pre-commit 创建文件:
#!/bin/sh
echo "🔍 正在跑 lint,请稍等..."
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lint 没过!不让你提交!"
exit 1
fi
echo "✅ 检查通过,放行!"
记得给执行权限:
chmod +x .git/hooks/pre-commit
💡 推荐用 husky 来管理 hook,配置更方便,还能提交到仓库让团队共享。
npx husky-init && npm install,然后按文档配。
总结
| 技巧 | 解决什么问题 |
|---|---|
git reflog | 代码"消失"了,救命用 |
git stash | 切分支前临时保存现场 |
git commit --amend | 补救刚提交的失误 |
git rebase -i | 清理 commit 历史,让 PR 好看 |
git bisect | 二分法找出引入 bug 的 commit |
.gitignore 早建 | 别把密码和 node_modules 推上去 |
git cherry-pick | 精准摘取某个 commit |
git lg(别名) | 好看的 log,一眼看懂分支结构 |
git diff --word-diff | 精准看改动 |
git hook | 自动化把关,不让问题代码提交 |
结语
Git 这个东西,学会 add、commit、push 只是刚入门。
真正用好 Git,是在被它搞崩过几次之后——你会发现它其实是个非常体贴的工具,只是你之前根本没读说明书。
希望这篇文章能让你少踩几个坑。
如果觉得有用,点个赞再走,你的赞是我继续写烂文章的动力 😄
📌 关注作者,持续分享老程序员踩坑实录。
下期预告:《Linux 命令行:那些年我以为自己懂,其实根本不懂的 20 个命令》
本文基于 Git 2.x 版本,示例在 Linux/macOS 环境下测试。Windows 用户请自备 Git Bash 或 WSL,别问我为啥 PowerShell 跑不了,那又是另一个故事了。