Git 日常用到的命令其实不多,真正让人慌的是"改错了怎么撤"。这篇把高频命令和撤销场景整理成一张对照表,需要的时候直接查。

日常高频命令

# 状态与差异
git status                  # 查看工作区状态
git diff                    # 未暂存的改动
git diff --staged           # 已暂存的改动

# 提交与同步
git add -A                  # 暂存所有改动
git commit -m "feat: 说明"   # 提交
git pull --rebase           # 拉取并变基,避免多余 merge 节点
git push                    # 推送

# 分支
git switch -c feature/xxx   # 新建并切换分支
git switch main             # 切回主分支
git branch -d feature/xxx   # 删除已合并的分支

# 临时存放
git stash                   # 暂存未提交的改动
git stash pop               # 恢复最近一次 stash

撤销操作对照表

先明确三个区域:工作区(已修改未 add)、暂存区(已 add 未 commit)、版本库(已 commit)。不同区域用不同的命令。

  • 丢弃工作区某个文件的改动 → git restore <file>
  • 把文件从暂存区撤回工作区 → git restore --staged <file>
  • 修改上一次的提交信息 → git commit --amend -m "新信息"
  • 撤销某次提交但保留历史 → git revert <commit>
  • 回退到某次提交并抹掉之后的历史 → git reset --hard <commit>

reset 的三种模式

reset 最容易用错的是参数,区别只在于"动到哪一层":

  • --soft:只移动 HEAD,改动留在暂存区。适合把多个提交合并成一个。
  • --mixed(默认):移动 HEAD 并重置暂存区,改动留在工作区。
  • --hard:HEAD、暂存区、工作区全部重置,改动直接丢弃
--hard 是唯一会真正弄丢代码的选项。执行前先确认改动已经 commit 或 stash,否则找不回来。

reset 还是 revert

判断标准只有一条:这个分支有没有别人在用

  • 本地分支、尚未推送:用 reset,历史干净,像什么都没发生过。
  • 已经推送到远程、或多人协作:必须用 revert。它会新增一个"反向提交"来抵消之前的改动,不改写历史,不会让队友的本地仓库和远程冲突。

rebase 的适用边界

rebase 的作用是"把我的改动接到最新的基线上",好处是历史是一条直线,没有分叉。但它会改写提交,所以遵循一条铁律:

只对尚未推送的本地提交做 rebase,永远不要 rebase 已经共享的分支。

日常最安全的用法是拉取时用 git pull --rebase,它只变基你本地那些还没推上去的提交。也可以在全局配置里一劳永逸:

git config --global pull.rebase true

小结

撤销之前先问自己两件事:改动在哪个区域?这个分支有没有别人?前者决定用 restore 还是 reset,后者决定用 reset 还是 revert。想清楚这两点,基本不会出事。

— 全文完 —