开发工具2026-03-20 11 分钟

Git 常用命令速查:从日常开发到救命操作

不是教你学 Git,是帮你在需要的时候快速找到那条命令。收藏这篇,关键时刻能救命。

用了五六年 Git,我常用的命令可能也就二十来个。但每隔几个月总会碰到一次「完了,代码搞丢了」的场景——要么是错误地 reset 了,要么是 rebase 冲突搞炸了。每次都要现查 Stack Overflow,查到的答案还经常过时。所以我把这些年真正用过的命令整理了一份,按场景分类,以后再遇到直接翻这篇就行。

说真的,Git 的命令行设计是我见过最反直觉的工具之一。checkout 一个命令又能切分支又能恢复文件,reset 的 --soft/--mixed/--hard 三个选项每次都要查一遍。好在 Git 2.23 之后出了 switch 和 restore,终于把职责分清了。但老项目的文档和 CI 脚本里全是 checkout,迁移成本太高,只能继续忍着。

1. 日常开发:每天都在用的命令

分支操作

# 创建并切换到新分支(推荐用 switch)
git switch -c feature/login
# 等价于旧写法:git checkout -b feature/login

# 切换到已有分支
git switch main

# 查看所有分支(含远程)
git branch -a

# 删除已合并的本地分支
git branch -d feature/login

# 强制删除未合并的分支(慎用)
git branch -D feature/experimental

# 重命名当前分支
git branch -m new-name

提交与暂存

# 查看工作区状态
git status

# 添加指定文件到暂存区
git add src/login.vue src/auth.ts

# 添加所有修改(不包括新文件和删除)
git add -u

# 交互式选择要暂存的代码块
git add -p

# 提交
git commit -m "feat: add login page"

# 修改最近一次 commit 的信息(未 push 时)
git commit --amend -m "feat: add login page with validation"

# 追加文件到上一次 commit(不改 message)
git add forgotten-file.ts
git commit --amend --no-edit

拉取与推送

# 拉取远程更新并合并
git pull

# 拉取但用 rebase 代替 merge(更干净的历史)
git pull --rebase

# 推送当前分支到远程
git push

# 首次推送新分支到远程
git push -u origin feature/login

# 强制推送(覆盖远程历史,团队协作慎用!)
git push --force-with-lease
# 比 --force 安全:如果远程有别人的新提交会拒绝

2. Stash:临时保存工作现场

正在写代码,突然被叫去修个紧急 bug。手上的改动还不想提交,又不能丢——这就是 stash 的用武之地。

# 保存当前工作区的修改
git stash

# 带描述信息保存(推荐,方便找回)
git stash push -m "login page WIP - form validation"

# 包括未跟踪的新文件
git stash push -u -m "include new files"

# 查看所有 stash
git stash list
# stash@{0}: On feature/login: login page WIP - form validation
# stash@{1}: On main: hotfix experiment

# 恢复最近的 stash(并删除)
git stash pop

# 恢复指定的 stash(不删除)
git stash apply stash@{1}

# 删除指定 stash
git stash drop stash@{1}

# 清空所有 stash
git stash clear

经验之谈:永远给 stash 加描述信息。不然过两天 git stash list 一看,全是 "WIP on main: abc1234",根本分不清哪个是什么。

3. 历史查看:谁改了什么、什么时候改的

# 查看提交历史(简洁模式)
git log --oneline

# 查看某个文件的修改历史
git log --oneline -- src/login.vue

# 漂亮的分支图
git log --oneline --graph --all

# 查看某次提交改了什么
git show abc1234

# 查看某个文件是谁在哪次提交改的(逐行追溯)
git blame src/login.vue

# 只看某几行的修改历史
git blame -L 10,20 src/login.vue

# 搜索 commit message
git log --grep="login"

# 搜索代码变更内容(谁引入/删除了这行代码)
git log -S "localStorage.getItem" --oneline

# 查看两个分支的差异
git diff main..feature/login

# 查看暂存区和最新 commit 的差异
git diff --cached

4. 撤销与回退:改错了怎么办

这大概是 Git 最让人困惑的部分了。不同的场景需要不同的撤销方式:

场景 1:修改了文件,还没 add

# 恢复单个文件到最近一次 commit 的状态
git restore src/login.vue

# 恢复所有文件
git restore .

场景 2:已经 add,还没 commit

# 从暂存区撤出(文件修改保留)
git restore --staged src/login.vue

# 撤出所有
git restore --staged .

场景 3:已经 commit,还没 push

# 撤销 commit,代码改动保留在工作区
git reset --soft HEAD~1

# 撤销 commit,代码改动保留但取消暂存
git reset --mixed HEAD~1  # 默认行为

# 撤销 commit,代码改动也丢弃(危险!)
git reset --hard HEAD~1

场景 4:已经 push 到远程

# 创建一个「反向 commit」来撤销(安全,不改历史)
git revert abc1234

# 撤销最近一次 commit
git revert HEAD

# 撤销一段连续的 commits
git revert HEAD~3..HEAD

reset 三种模式对比:

模式HEAD暂存区工作区
--soft回退保留保留
--mixed回退清除保留
--hard回退清除清除

5. 救命操作:代码「丢了」别慌

在 Git 里,只要 commit 过,数据几乎不可能真正丢失。即使 reset --hard 了,也有办法找回来。

reflog:Git 的「后悔药」

# 查看所有 HEAD 的移动记录(包括被 reset 掉的 commit)
git reflog

# 输出类似:
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: feat: add payment module
# ghi9012 HEAD@{2}: commit: fix: order calculation

# 找到那个被误删的 commit hash,恢复到那里
git reset --hard def5678

# 或者更安全地,把它捡回来创建新分支
git switch -c recover-branch def5678

cherry-pick:从别的分支「偷」一个 commit

# 把某个 commit 应用到当前分支
git cherry-pick abc1234

# 一次 pick 多个
git cherry-pick abc1234 def5678

# 只应用改动,不自动 commit
git cherry-pick --no-commit abc1234

记住这个原则:在 Git 中,只要你 commit 过,数据在 30 天内(默认 gc 周期)都可以通过 reflog 找回来。所以养成勤 commit 的习惯,哪怕是半成品代码也先 commit,以后再用 rebase squash 合并。

6. 合并与变基:merge vs rebase

git merge

# 将 feature 分支合并到 main
git switch main
git merge feature/login

保留完整的分支历史,会产生一个 merge commit。适合公共分支(main/develop)的合并。

git rebase

# 将 feature 的 commit 搬到 main 最新位置上
git switch feature/login
git rebase main

重写提交历史,让 commit 看起来像是在最新代码上连续开发的。历史更干净,但不要对已 push 的 commit 做 rebase。

解决冲突

# 冲突时,Git 会在文件中标记冲突区域:
# <<<<<<< HEAD
# 你的改动
# =======
# 别人的改动
# >>>>>>> feature/other

# 手动解决后:
git add resolved-file.ts
git merge --continue  # 或 git rebase --continue

# 不想合了,放弃
git merge --abort     # 或 git rebase --abort

7. 实用小技巧

设置常用别名

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --all"
# 之后 git lg 就能看到漂亮的分支图

清理已合并的远程分支

# 清理本地缓存的已删除远程分支
git fetch --prune

# 查看已合并到 main 的本地分支
git branch --merged main

# 批量删除已合并的分支(排除 main 和当前分支)
git branch --merged main | grep -v "main\|*" | xargs git branch -d

用 bisect 定位引入 bug 的 commit

# 启动二分查找
git bisect start
git bisect bad          # 当前版本有 bug
git bisect good v1.0.0  # 这个版本没有 bug

# Git 会自动切换到中间的 commit
# 你测试后标记好坏:
git bisect good  # 或 git bisect bad

# 几轮后 Git 就能定位到第一个引入 bug 的 commit
# 结束
git bisect reset

相关阅读

想深入了解 Git 工作流和团队协作规范?推荐阅读我们的另一篇文章:Git 工作流最佳实践:从 commit 规范到分支策略,涵盖 Conventional Commits、分支策略对比和 rebase 实战。