老程序员的 Git 避坑手册:这 10 个命令,我当年要是早知道就好了

0 阅读8分钟

🧓 老程序员的 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 popstash 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 写早不写晚,写晚哭断肠

这不是命令技巧,这是血的教训。

新手常见的神操作:

  1. node_modules(500MB)提交上去了
  2. 把含密码的 .env 文件推到 GitHub 了
  3. 把整个 .idea 文件夹(JetBrains 配置)污染了团队仓库

标准做法:项目第一天就建好 .gitignore

推荐直接用生成工具:gitignore.io,选你的技术栈,一键生成。

已经误提交的文件,补救方法:

# 从 Git 追踪中移除,但本地文件保留
git rm --cached 误提交的文件.env
echo "*.env" >> .gitignore
git commit -m "chore: 移除敏感文件,从今天起好好做人"

⚠️ 但是:如果 .env 已经 push 到公共仓库了,立刻去改密码!!git rm 只是让文件消失在当前,历史记录里还查得到。想彻底抹掉,需要 git filter-branchBFG 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 这个东西,学会 addcommitpush 只是刚入门。

真正用好 Git,是在被它搞崩过几次之后——你会发现它其实是个非常体贴的工具,只是你之前根本没读说明书。

希望这篇文章能让你少踩几个坑。

如果觉得有用,点个赞再走,你的赞是我继续写烂文章的动力 😄


📌 关注作者,持续分享老程序员踩坑实录。
下期预告:《Linux 命令行:那些年我以为自己懂,其实根本不懂的 20 个命令》


本文基于 Git 2.x 版本,示例在 Linux/macOS 环境下测试。Windows 用户请自备 Git Bash 或 WSL,别问我为啥 PowerShell 跑不了,那又是另一个故事了。