git add后悔了可用git restore --staged 或git reset 撤销暂存,切勿用git checkout -- 以免丢弃工作区修改;git commit -a仅提交已跟踪文件的变更,不包含新增未跟踪文件。

Git 常用命令不是背出来的,是按场景“查”出来的 —— 重点不是记全,而是知道在什么情况下该用哪个命令、参数差在哪、一错就丢数据。
git add 后悔了怎么办:撤销暂存的几种方式
刚 git add . 完,发现误加了日志文件或配置文件,但还没 git commit,这时候不能硬删工作区文件,得从暂存区撤出来。
-
git restore --staged <file></file>(Git 2.23+ 推荐):只撤销暂存,工作区不变 -
git reset HEAD <file></file>(旧版兼容写法):效果同上,但HEAD是冗余的,可简写为git reset <file></file> -
git restore --staged .:撤销当前目录所有暂存文件 - ⚠️ 别用
git checkout -- <file></file>:这是丢弃工作区修改,不是撤暂存,容易覆盖未保存的编辑
git commit -a 和 git add + git commit 的区别在哪
git commit -a 看似省事,但它的行为有明确边界:它只会把「已被 Git 跟踪过」的文件的修改和删除纳入提交,对新增的未跟踪文件(untracked)完全无视。
- 适用场景:
git commit -a -m "fix typo"快速提交已知文件的小修小改 - 风险点:如果你刚加了一个新配置文件
config.local.js并修改了它,git commit -a不会把它包含进去 —— 它压根没被git add过 - 对比:
git add . && git commit -m "msg"会把所有新增/修改/删除都纳入(除非被.gitignore拦住),更可控
git diff 看不到刚改的文件?检查这三个位置
git diff 默认只比较「工作区」和「暂存区」,很多新人改完文件执行 git diff 却没输出,以为没改成功,其实是命令作用域理解错了。
-
git diff:工作区 vs 暂存区(最常用,确认哪些改动还没add) -
git diff --cached或git diff --staged:暂存区 vs 最后一次commit(确认即将提交的内容) -
git diff HEAD:工作区 vs 最后一次commit(绕过暂存区,看全部差异) - 常见误判:改完文件后直接
git diff没反应 → 其实是文件已git add过,差异已进暂存区,此时要用git diff --staged
git push 失败说 “non-fast-forward”,别急着 --force
当你本地分支落后远程(比如别人先推了新提交),git push 会拒绝,报错里通常带 non-fast-forward。这时强制推送 git push --force 很危险,尤其在共享分支上会抹掉他人提交。
- 正确做法:先
git pull --rebase origin <branch></branch>,把你的提交“叠”在别人更新之后 - 如果已用
git pull(默认 merge),产生了一堆 merge 提交,又想线性历史,可以用git rebase -i origin/<branch></branch>交互式变基整理 - 仅当明确知道自己在重写公共历史(如修复刚推错的敏感信息),才用
git push --force-with-lease(比--force安全,会检查远程是否被他人更新)
Git 命令组合多、参数语义微妙,真正卡住人的往往不是“不会用”,而是“不知道自己用错了哪一层”。比如 git reset 的 --soft/--mixed/--hard 区别,差一个参数就可能丢掉刚写的几十行代码 —— 这类关键分界点,必须结合当前 HEAD、index、worktree 三者状态一起看,不能只记命令。











