15 个让初级与高级开发者拉开差距的 Git 命令

原文:https://dev.to/akashguptasky/15-git-commands-that-quietly-separate-juniors-from-seniors-a3m(作者 @akashguptasky)

每个人都会 addcommitpush——那只是入场券,不是比赛本身。

那些开发速度飞快的人——从不丢失工作成果、从不提交混乱的历史、rebase 翻车也从不慌乱的开发者——都悄悄共享着同一套工具箱。这不是什么高级的 "Git 魔法",而是大约 15 个一下午就能学会、之后整个职业生涯都在用的命令。

如果非要说出一个不动一行业务代码就能预示开发者资历的技能,那就是对 Git 的熟练度。下面就是我每周真正会用到的那 15 个命令,以及那些没人提醒过你的坑。

1. git switchgit restore——别再什么事都用 checkout

多年来 checkout 干着两件互不相干的事:切换分支,以及丢弃文件改动。这种职责超载引发过不少真实的事故。现代 Git 把它拆开了:

git switch main            # 切换分支
git switch -c feature/pay  # 创建分支并切换
git restore src/app.js     # 丢弃文件中的改动
git restore --staged x.js  # 取消暂存,保留修改


坑: git restore <file> 会永久丢弃未提交的改动,没有撤销。请谨慎使用。

2. git add -p——像外科手术一样提交

一个文件里改了五处互不相关的东西?别把它们全部塞进同一个提交。按 hunk(块) 来暂存:

git add -p


Git 会带你逐个检查每处改动:y(暂存)、n(跳过)、s(进一步拆分)、e(手动编辑 hunk)。这一个习惯,就决定了你的提交历史是可读的,还是沦为一片 "misc fixes" 墓地。

3. git commit --amend——修复上一次提交,而不是补一个新提交

忘了加文件?提交信息打错字?别为此补一个 fix typo 提交:

git add forgotten.js
git commit --amend --no-edit   # 并入上次提交,保留原提交信息
git commit --amend             # 或者连提交信息一起改


坑: amend 会重写提交(生成新的 hash)。本地没问题;如果已经推送了,就需要强制推送——见第 13 条。

4. git commit --fixup + --autosquash——修改更早的提交

--amend 只能修最近一次提交。要修的是三笔之前埋着的提交怎么办:

git commit --fixup=<hash>              # 生成一个标记为 "fixup!" 的提交
git rebase -i --autosquash main        # Git 会自动把它排到目标提交旁边


这是大多数人永远学不会的专业操作。你的修复会自动落到它该在的位置。

5. git rebase -i——历史编辑器

交互式 rebase 让你重塑最近的一批提交:rewordsquashfixupdropedit,还能调整顺序——只需编辑一份列表。

git rebase -i HEAD~5


add validationfix validationactually fix it 三个提交整理成一个干净的 Add form validation规则: 只重写还没有被别人拉取过的提交。

6. git stash——搁置半成品工作,不提交垃圾

线上出故障了,而你的功能才写了一半?先 stash 起来:

git stash push -u -m "wip: checkout flow"   # -u 也会暂存未跟踪文件
git stash -p                                # 只暂存选中的 hunk
git stash list
git stash show -p stash@{0}
git stash pop                               # 应用并移除
git stash apply stash@{0}                   # 应用,但保留在列表中


坑: 不加 -u,新建的未跟踪文件会留在原地。记得给 stash 起名字——「未来的你」不会记得 stash@{3} 是什么。

7. git cherry-pick——只挑一个提交,不要整个分支

你只需要另一个分支上的某一个提交——一个配置修复、一个 hotfix,别的都不要:

git cherry-pick <hash>
git cherry-pick -x <hash>   # 在提交信息中记录 "cherry picked from…"
git cherry-pick -n <hash>   # 只应用不提交(先攒几个,再一次提交)


把单个修复移植到发布分支,用它正合适。

8. git bisect——二分定位引入 bug 的提交

「大概在过去 200 个提交里的某个时候」出现了 bug?别猜。让 Git 用大约 8 步找到它:

git bisect start
git bisect bad                 # 当前提交是坏的
git bisect good v1.4.0         # 这个旧版本是好的
# Git 检出中点——你测试一下,然后标记:
git bisect good   # 或者: git bisect bad
# ……重复直到 Git 指出罪魁祸首
git bisect reset


更棒的是,可以自动化:

git bisect run npm test


Git 会在每个中点运行你的测试,自动找出引入问题的提交。第一次看它跑完,你会觉得这简直是开挂。

9. git worktree——两个分支、两个目录、一个仓库

切换上下文的最佳秘密武器。与其把功能开发 stash 起来去修生产 bug,不如把另一个分支检出到单独的文件夹里:

git worktree add ../hotfix main
# 在 ../hotfix 里修复、提交、推送——你的功能开发完全不受影响
git worktree remove ../hotfix


不用 stash,不用折腾重新构建,思路也不会被打断。

10. git log -Sgit log -L——侦探模式

「这一行是什么时候出现的?谁删了这个函数?」

git log -S "calculateTax" --oneline    # 新增或删除了该字符串的提交
git log -p -L :calculateTax:tax.js     # 某个函数的完整历史


这个 "pickaxe"(-S)搜索终结过的「这行谁写的、为什么要这么写」争论,比任何会议都多。

11. git blame -w -C —— 正确的逐行历史查看方式

git blame -w -C src/auth.js


-w 忽略仅含空白的改动;-C 追踪被移动或复制的代码——这样 blame 到的就是真正的作者,而不是运行格式化工具的人。然后阅读提交是为了了解原因,而不是为了追责。

12. git reflog —— “撤销”的撤销按钮

用错误的 reset 毁掉了一个分支?Git 几乎记录 HEAD 的每一次移动:

git reflog
# 821cd77 HEAD@{1}: commit: Add authentication   ← 就在这里
git branch rescue 821cd77   # 安全地恢复到新分支


限制: reflog 只能恢复 Git 已经存储的东西(提交、stash)。从未提交的工作就没了。换句话说:尽早提交,频繁提交。

13. git reset --soft / --mixed / --hard(以及安全的强制推送)

一个命令,三种“回退”级别,每一种都回答“我的改动会怎样?”

git reset --soft  HEAD~1   # 撤销提交,保留改动为已暂存(STAGED)
git reset --mixed HEAD~1   # 撤销提交,保留改动为未暂存(UNSTAGED,默认)
git reset --hard  HEAD~1   # 撤销提交,丢弃改动(危险)


任何历史重写之后,安全地推送:

git push --force-with-lease   # 如果别人已推送,就拒绝覆盖


始终使用 --force-with-lease 而不是 --force。这之间的区别是“哎呀”和“我刚刚删掉了队友一下午的工作”的区别。

14. git revert —— 在共享分支上撤销,而不重写历史

一个坏提交已经推到了 main/develop不要对共享分支进行 reset + force-push。创建一个反向提交:

git revert <hash>


历史保持真实:改动发生过、它破坏了东西、它被还原——所有人都能看到轨迹。经验法则:共享分支 → revert;私有分支 → reset。

15. git rerere —— Git 会记住你如何解决冲突

Reuse Recorded Resolution(复用已记录的解决方案)。 启用一次:

git config --global rerere.enabled true


此后当你解决冲突时,Git 会记录下来。再次遇到相同冲突(在长时间 rebase 中非常常见),它会自动重放你的解决方案。冷门、少用、近乎神奇。


这些命令背后的共同模式

注意主题:其中大部分都是为了让你保持干净、诚实的历史,并且永不丢失工作。这才是 Git 高级用法的真正含义——不是死记标志参数,而是拥有快速行动又不破坏东西的反应能力。

原文:https://dev.to/akashguptasky/15-git-commands-that-quietly-separate-juniors-from-seniors-a3m(作者 @akashguptasky)

发布评论
全部评论(0)