Git 里几个用了好几年才知道的命令
用 Git 好几年,大部分时间翻来覆去也就那十来个命令:add、commit、push、pull、checkout、merge、rebase,外加偶尔一个 stash。下面这几个是后来才知道的,每个都在某次让我少折腾了半天,记下来。
git switch 和 git restore
git checkout 身兼两职:既能切分支,又能还原文件。git checkout foo 到底是切到 foo 分支,还是还原名叫 foo 的文件,取决于当前有没有这么一个分支。我就在这上面栽过一次,本想切分支,结果把一个文件的改动全清掉了。
Git 2.23 以后把这两件事拆开了:
git switch feature # 切分支
git switch -c feature # 新建并切过去
git restore app.py # 丢弃工作区里的改动
git restore --staged app.py # 取消暂存,改动还在
名字就说明了要做什么,不会再搞混。
--fixup 加 --autosquash
提交了一个功能,过一会儿发现里面有个错字。以前的做法是再提交一个"fix typo",或者手动 rebase -i 把它挪上去再改成 squash。现在是:
git commit --fixup=a1b2c3d
git rebase -i --autosquash main
rebase 的编辑界面打开时,fixup 提交已经自动排在目标提交下面并标好了 fixup,直接保存退出就行。再设一下 git config --global rebase.autoSquash true,连参数都不用加。
git log -S:找某段代码是什么时候加进来、什么时候没的
git log -S'retry_count' --oneline
它会列出所有让 retry_count 出现次数发生变化的提交,也就是加进来的那次和删掉的那次。想找"这个函数是谁、在什么时候删的",比翻 blame 快多了。想用正则就换成 -G。
git worktree:不用 stash 也能临时切出去
手上改了一堆东西还没法提交,这时候来了个紧急修复。以前只能 stash 起来,切分支,修完再切回来 pop,中间还可能冲突。
git worktree add ../hotfix main
cd ../hotfix
# 修,提交,推送
cd - && git worktree remove ../hotfix
同一个仓库,另开一个目录检出另一个分支,两边互不打扰,.git 也只有一份。
git bisect run:让 Git 自己找出是哪次提交搞坏的
知道 v1.4 还是好的,现在坏了,中间隔了两百个提交。手动二分要试七八次,每次都得编译、跑测试。如果有一个脚本能判断好坏,退出码 0 表示好、非 0 表示坏,就可以全交给 Git:
git bisect start HEAD v1.4
git bisect run ./check.sh
git bisect reset
去倒杯水回来,它就告诉你第一个坏掉的提交是哪个。
--force-with-lease
改写过历史的分支需要强推时,用它代替 --force。如果远端在你上次拉取之后被别人推过新提交,它会拒绝推送,而不是把别人的提交悄悄覆盖掉。我已经给它设了别名,--force 基本不再用了。
最后说一句 git reflog
只要做过提交,几乎就丢不了。reset 错了、rebase 搞乱了、分支删了,git reflog 里都能看到 HEAD 之前指向过哪里,找到那一行再 git reset --hard 回去就行。知道有这个兜底以后,我对 rebase 的恐惧少了一大半。