Git:删除分支、合并与撤销错误的 push
August 2, 2026 · – 访客
这三件事时不时就会碰上,可命令却总是记不牢,一次和下一次之间怎么也串不起来。所以干脆把它们好好写下来。
删除分支
git branch -d feature-x
这是安全的版本——Git 会先检查,如果 feature-x 里有还没进入你当前分支的提交,就会拒绝删除。如果你确定要删,可以强制执行: (1)
git branch -D feature-x
不过这只是本地删除。如果这个分支在远程(比如 GitHub 上)也存在,你还得单独把它删掉:
git push origin --delete feature-x
有一点值得知道:删除分支其实并不会删除它的提交。它们只是变得无人引用,继续留在仓库里,直到 Git 的垃圾回收机制最终把它们清理掉,而这可能要等上好一阵子。所以 git branch -D 比看上去更宽容——如果你删错了分支,通常还是有办法找回来的(下面 reflog 那一节会详细说)。我不会把这当成一个可靠的计划,但知道它存在还是挺让人安心的。
合并分支
通常的做法是:切换到你想要合并进去的那个分支,然后把另一个分支合进来。
git checkout main
git merge feature-x
接下来会发生什么,取决于自你分支出去之后 main 有没有继续前进。如果没有,Git 只是把 main 的指针直接滑动到 feature-x 的位置——这就是快进(fast-forward),不涉及任何合并提交。如果这期间 main 已经往前走了,Git 就会创建一个真正的合并提交,把两条历史线绑在一起 (2)。
有时候即便快进本来是可行的,你也会想要那个合并提交——它会在历史里留下一个清晰可见的标记,表明曾经存在过一个 feature 分支并被合并了,而不是让改动悄无声息地融进去。为此可以用:
git merge --no-ff feature-x
如果双方改动了同样的行,Git 会停下来,把冲突留给你去处理:
git status
这会列出哪些文件存在冲突。逐个打开,你会在互相竞争的改动周围看到 <<<<<<<、======= 和 >>>>>>> 标记——挑出真正应该保留的内容,删掉这些标记,然后:
git add resolved-file.txt
git commit
要是场面乱得不值得再收拾下去,你完全可以直接抽身走人:
git merge --abort
这会把一切恢复到你开始合并之前的样子,分毫不差。
撤销一次错误的 push
这是最让人恐慌的情况,但说实话,这种恐慌通常没什么必要——不过你选择用哪种方式来补救,这里确实很重要。
只要有一丁点可能别人已经 pull 过这个分支,就别去动历史。改为添加一个新的提交,把旧的撤销掉:
git revert <bad-commit-sha>
git push
这是个无聊但永远安全的选项。它不会重写任何东西——只是在上面加一个提交,把错误抵消掉,这样每个人的历史都保持同步,没人需要在自己那边做任何特殊处理 (3)。
如果这个分支确确实实只属于你,还没有人 pull 过,你就可以倒回去重写: (4)
git reset --hard <last-good-commit-sha>
git push --force-with-lease
用 --force-with-lease,别用纯粹的 --force,哪怕只是出于习惯也该这样。这个区别比看上去重要得多:--force-with-lease 会检查自你上次 fetch 以来有没有人向这个分支 push 过,如果有就拒绝执行。纯粹的 --force 什么都不检查——它会毫不犹豫地覆盖别人的工作,连一句警告都没有 (5)。
如果你盯着终端,努力回想上一个还算正常的提交到底是哪个——git log 在这里帮不上忙,因为它只显示从你当前位置能够到达的提交,而你已经 reset 掉的那些不在其中。你真正需要的是:
git reflog
它会显示你的分支最近指向过的每一个位置,包括那些已经掉出正常历史记录的。往回翻到事情出错之前,然后: (6)
git reset --hard HEAD@{2}
(换成真正符合你情况的位置或 SHA)。reflog 只保存在你自己的机器上,通常会把记录保留大约 90 天,所以与其说它是"应对错误 push 的紧急撤销手段",不如说它是那种"我好像刚把什么搞坏了"时的通用安全网——即便在这个具体场景之外,也值得记住它的存在。
结语
这三件事其实都依赖同一个底层事实:Git 几乎从不立刻丢弃任何东西。被删除的分支、被 reset 掉的提交、分支上的旧位置——它们停留的时间都比看上去要长。这才是真正让 -D、reset --hard 和 force-push 在日常使用中足够安全的原因,前提是你知道万一其中哪一个出了差错,该去哪里找回来。
相关阅读
- 理解 Make — 到底是什么触发了重新构建
延伸阅读
- git-branch — 分支的创建、列出与删除。
- git-merge — 合并策略与冲突解决。
- git-revert — 通过创建新提交来撤销旧提交。
- git-reset — 移动分支指针,以及
--soft、--mixed、--hard之间的区别。 - git-push: --force-with-lease — 为什么它比
--force更安全。 - git-reflog — 找回那些在正常历史记录中已经看不到的提交。
评论