学习中心/工程实践/Git/Git 进阶:改历史之前,先别动别人的 main
· Git · 进阶
Git 进阶:改历史之前,先别动别人的 main
rebase、revert、reflog、cherry-pick。进阶是为了把历史整理干净,不是炫技。

已经推上去的 main,不是你的草稿纸
进阶命令能改历史。改自己还没推的分支,可以。改大家正在用的 main,是事故。默认:revert 公开历史,rebase 只动本地。
- 本地rebase -i
- 公开git revert
- 找回git reflog
- 摘一次cherry-pick
1. 本地整理:rebase -i
合进 main 之前,把「修一下」「再修一下」收成几条说得清的提交。只对自己的短分支做。
- 把当前分支接到 main 上,并打开待办:pick / squash / reword
git rebase -i main - 乱了就停。历史回到这条命令之前
git rebase --abort
2. 撤掉一次已经发布的:revert
reset 是把指针往后拨,别人已经拉走的提交会对不上。revert 是新增一次「反过来」的提交,公开线上用这个。
- 用一次新提交,抵消最新那次。不改别人已经拿到的历史
git revert HEAD - 本地丢弃最新一次。没推过才能这样。推过了不要对共享分支用
git reset --hard HEAD~1
3. 找回来:reflog
HEAD 最近去过哪,reflog 都记着。rebase 错了、reset 错了,先看这里,再 checkout 那个 SHA。
- 看:当前仓库里 HEAD 的每一步
git reflog - 从那个还在的提交开一条恢复分支
git switch -c recover abcdef1
4. 只要那一次:cherry-pick
- 找到要摘的那次提交
git log --oneline - 把那一次接到当前分支,不必整条分支 merge
git cherry-pick abcdef1
5. 必须覆盖远程时
rebase 过已经推过的短分支,有时要强推。用 --force-with-lease,有人先推了会拒绝。不要 git push --force 对 main。
- 覆盖远程,但别人先推了就停
git push --force-with-lease
6. 谁引入的:bisect
- 开始对分。再标一个坏的、一个好的
git bisect start - 当前这次是坏的
git bisect bad - 这个标签还是好的。Git 会检出中间点让你测
git bisect good v1.2.0 - 查完,回到 bisect 之前
git bisect reset
7. 两份目录同时干活:worktree
同一仓库两份工作区,分支互不覆盖。HiPMMCode 的 Legion 默认也走这条。修热问题和做大改可以并行。
- 在隔壁目录检出 hotfix/login,原来的目录不动
git worktree add ../repo-hotfix hotfix/login - 看现在挂了几份工作区
git worktree list
进阶是为了不把同事的历史弄乱。会 revert、会 reflog、会 force-with-lease,就够在团队里用了。