Git 命令速查

按「我正在做什么」分组的 Git 命令表。会丢代码或改历史的操作单独标了风险,选之前先看一眼。

显示 67 / 67 条命令

三种撤销到底用哪个

只改了文件还没 add,用 git restore 文件路径 把工作区恢复到 HEAD 的样子;已经 add 进暂存区,用 git restore --staged 文件路径 退回工作区;已经 commit 了,才轮到 git reset。这三步是递进的,从哪一步开始出错就从哪一步往回撤,能少走很多弯路。

reset 的三种模式区别在「改动往哪去」:--soft 把改动留在暂存区(想重新组织提交时用),--mixed 留在工作区(这是默认值,想重新挑文件时用),--hard 直接丢掉。已经推到远程的提交不要用 reset 改,改用 git revert 生成一个反向提交,历史不动,别人也不会分叉。

rebase 和 merge 怎么选

简单说:合别人的分支用 merge,整理自己的分支用 rebase。merge 保留真实的合并点,历史如实反映「什么时候合的」;rebase 把提交重新摆放,得到一条直线,看着舒服但改写了哈希。判断标准只有一条——这些提交有没有被别人拉走过。没有就可以放心 rebase,有就只能 merge。

配套的一条纪律是:主分支(main、master、release)永远只快进合并,别 rebase。合并前用 git pull --ff-only 而不是默认的 pull,它会在无法快进时直接报错,而不是悄悄生成一个合并提交,这能避免绝大部分「本地历史怎么多出一堆交叉线」的困惑。

12 条会丢东西的命令

表里标了「注意」的 12 条都属于删了就找不回来的类型。git reset --hard 和 git clean -fdx 丢掉的是从未提交过的内容,Git 里没有任何地方存着它们,reflog 也救不了。git stash drop 丢掉的暂存现场同样尴尬,它不属于任何分支,只能靠 git fsck --lost-found 去翻悬空对象,成功率不高。

会改写历史的(rebase、commit --amend、filter-repo)本身不丢内容,但会让别人的本地仓库和远程对不上,协作者必须重新克隆或做一次麻烦的复位。强推时坚持用 --force-with-lease 而不是 --force,前者会在远程被别人更新过时拒绝执行,这一个参数能挡掉最典型的那种事故。

这份表的适用边界

Git 2.23 之后官方把 checkout 的两种用途拆成了 git switch(切分支)和 git restore(恢复文件),表里两套命令都保留了,老版本系统上还能用。git filter-repo 是官方推荐替代 filter-branch 的独立工具,多数发行版的仓库里没有,需要单独装(pip install git-filter-repo 或 brew install git-filter-repo),表里列出的 filter-branch 用法在新项目里已经不建议再用。