外观
03 · 日常改代码与提交
一天里用得最多的一层:把工作区的改动,有选择地变成一次 commit。
git status
作用: 显示当前分支、与上游的 ahead/behind、工作区与暂存区差异、未跟踪文件、进行中的 merge/rebase。
改动范围: 只读。
典型场景: 每次 add / commit / 切分支之前先看一眼;冲突中看还剩哪些文件没解决。
常用写法:
bash
git status
git status -sb # 短格式,适合配 alias.st
git status --untracked-files=all不要这样用: 看都不看就 git add . 再 commit。密钥、调试打印、本地配置很容易混进去。
做错了怎么办: 这条命令不会做错。输出看不懂时,对照 00 章三区图。
git add
作用: 把工作区改动写入暂存区,为下一次 commit 做准备。
改动范围: 暂存区。工作区文件不动。
典型场景:
- 只提交其中一个文件,其它半成品留着。
- 一个文件里既有功能又有调试,用
-p一块一块挑。 - 批量暂存已跟踪文件的修改,但不把新的未跟踪垃圾加进去。
常用写法:
bash
git add src/login.ts
git add -p # 交互挑选 hunk
git add -u # 已跟踪文件的修改和删除,不含新文件
git add . # 当前目录往下所有改动(受 .gitignore 约束)不要这样用: git add . 之前不看 status;在仓库根目录把 .env、大二进制、IDE 文件一起加进去。
做错了怎么办: 多暂存了,撤出暂存区、保留工作区改动:
bash
git restore --staged src/login.ts
# 旧写法:git reset HEAD src/login.tsgit commit
作用: 把暂存区拍成一次新的 commit,移动当前分支指针和 HEAD。
改动范围: 本地历史。不自动推远程。
典型场景: 完成一个可审查的小步骤:修一个 bug、加一个函数、改一处文案。
常用写法:
bash
git commit -m "fix: 拒绝空密码登录"
git commit # 打开编辑器写更长说明
git commit -am "fix: ..." # 把已跟踪文件的改动一并 add 再 commit;新文件不会被加进去好的说明:写「做了什么、为什么」,不写「改了点东西」。团队若有 Conventional Commits,跟着用 feat: / fix: / chore:。
不要这样用:
git commit -a漏掉刚新建的文件还以为提交全了。- 用
git commit --amend去改已经 push 且别人可能基于它开发的提交。
git commit --amend(改最后一次提交)
作用: 用「当前暂存区 + 新的提交说明」替换最新一次 commit(SHA 会变)。
改动范围: 改写本地历史(最新一颗)。
典型场景(仅限该提交尚未 push,或你确定只有自己在用这条分支):
- 说明写错了。
- 漏
add了一个文件。
bash
git add 漏掉的文件
git commit --amend --no-edit # 只补文件,不改说明
git commit --amend -m "新的说明" # 改说明不要这样用: main 上已经 push 的提交拿去 amend,再 push --force。同事的历史会分叉。
做错了怎么办: amend 之前的那颗 commit 还在 reflog:
bash
git reflog -10
git reset --soft HEAD@{1} # 回到 amend 前,改动仍在暂存区git restore
作用: 从指定来源恢复文件到工作区和/或暂存区。专门负责「文件」,不负责「切分支」。
改动范围: 工作区和/或暂存区。默认不移动 HEAD。
典型场景:
- 这个文件改砸了,回到最后一次提交。
- 暂存多了,撤出暂存但代码留着。
- 对比其它分支上的同名文件,把某文件换成那边的版本。
常用写法:
bash
# 丢弃工作区改动,回到 HEAD(暂存区不受影响)
git restore src/login.ts
# 撤出暂存区,工作区保留
git restore --staged src/login.ts
# 暂存区和工作区都回到 HEAD(等价于丢掉该文件未提交的全部改动)
git restore --source=HEAD --staged --worktree src/login.ts
# 把某文件恢复成 main 上的样子
git restore --source=main src/login.ts旧写法对照:
| 现在 | 以前 |
|---|---|
git restore 文件 | git checkout -- 文件 |
git restore --staged 文件 | git reset HEAD 文件 |
不要这样用: 对未 add 过的新文件执行 restore 期望「找回刚才删的内容」——未跟踪文件不在 Git 里。想清未跟踪文件用 clean,那是删除不是恢复。
做错了怎么办:
- 只是
--staged:工作区还在,再add回去。 - 已经
restore丢掉工作区:若曾经add过,blob 可能还能用git fsck --lost-found碰运气,见 急救手册。从未 add 的,看编辑器 Local History / 回收站。
git rm
作用: 从工作区和暂存区删除文件,下次 commit 会记录删除。
改动范围: 工作区 + 暂存区。
典型场景: 这个源文件确定不要了;或者只要停止跟踪(--cached)。
常用写法:
bash
git rm src/obsolete.ts
git rm -r docs/old/
git rm --cached secrets.env # 停止跟踪,磁盘文件留下不要这样用: 把 git rm 和资源管理器删除混着用,又不 status,最后一次提交里漏删或误删。
做错了怎么办: 还没 commit:
bash
git restore --staged --worktree src/obsolete.ts已经 commit 但未 push:git reset --soft HEAD~1 或再把文件从上一提交检出。已 push:再提交一次把文件加回来,或 revert 那次删除提交。
git mv
作用: 重命名或移动已跟踪文件,并一次性放进暂存区。
改动范围: 工作区 + 暂存区。
典型场景: 文件改名、目录调整。等价于「重命名 + git add 旧路径和新路径」,Git 之后靠相似度检测把它显示成 rename。
bash
git mv src/login.ts src/auth/login.ts
git commit -m "refactor: 移动登录模块"直接在资源管理器改名也可以,再用 git add -A,效果类似。git mv 只是少一步。
做错了怎么办: 再 git mv 回去,或 git restore --staged --worktree 后手动改回。
git clean · 危险
作用: 删除未跟踪文件(和可选的目录)。不动已跟踪文件。
改动范围: 工作区里 Git 不认识的文件。删了 Git 救不回。
典型场景: 构建产物、误生成的大文件、跑测试留下的垃圾。想要一个「和最新提交一模一样的工作区」。
常用写法(务必先演练):
bash
git clean -n # dry-run:只打印会删什么
git clean -nd # 连将要删的目录一起预览
git clean -fd # 真删:未跟踪文件 + 目录
git clean -fdx # 连被 ignore 的也删(node_modules 等会没)不要这样用: 不看 -n 就 -fd / -fdx。新建了半天还没 add 的源文件会一起消失。
做错了怎么办: Git 无能为力。立刻去:
- 编辑器的 Local History / Timeline
- 系统回收站
- 云盘或备份
预防:不确定的先 git add 或 git stash -u 再 clean。完整说明见 急救手册 · clean。
一条建议工作流
bash
git status -sb
git diff # 看没暂存的
git add -p
git diff --staged # 看即将提交的
git commit -m "..."
git status -sb # 确认干净或只剩有意留下的改动需要和远程同步时再去 07 章。想扔掉「已经 commit 但还没 push 的几笔」,用 06 章的 reset,不要在这里 clean。
上一章:02 · 创建与克隆 · 下一章:04 · 查看状态、差异与历史