git分支撤回

40 阅读3分钟

一:已经推送到远程仓库

1. 使用 git revert(安全方案)

这会创建一个新的提交来撤销合并,不修改历史:

# 查看合并提交的 ID
git log --oneline

# 撤销合并提交(-m 1 表示保留当前分支的修改)
git revert -m 1 <合并提交的commit-id>

# 推送到远程
git push origin <分支名>

这里保留当前分支的修改是指:

合并提交的特殊性

普通的提交只有一个父提交,但合并提交(merge commit)有两个父提交

bash

# 查看合并提交的父提交
git log --pretty=%P -1 <merge-commit-id>

# 输出示例:def5678 ghi9012
# 第一个父提交 (def5678) - 合并时的当前分支(main)
# 第二个父提交 (ghi9012) - 被合并进来的分支(feature)

-m 参数的作用

-m 1 告诉 Git:"撤销合并时,保留第一个父提交(当前分支)的内容"

bash

# 图示说明
# 合并前的状态:
      A---B---C  (main)
     /
D---E---F---G  (feature)

# 合并后:
      A---B---C---M  (main)
     /           /
D---E---F-------G  (feature)

# M 的父提交:
# - 父提交1: C (main分支的提交)
# - 父提交2: G (feature分支的提交)

-m 1 vs -m 2

bash

# 保留 main 分支的修改,丢弃 feature 的修改
git revert -m 1 M

# 保留 feature 分支的修改,丢弃 main 的修改
git revert -m 2 M

实际例子

bash

# 假设在 main 分支上合并了 feature 分支
git checkout main
git merge feature

# 想撤销合并,恢复 main 分支原来的样子
git revert -m 1 HEAD

更直观的理解

把合并提交想象成一个十字路口:

  • -m 1:沿着原路返回(保留原分支)
  • -m 2:沿着岔路返回(保留合并进来的分支)

bash

# 场景1:合并错了分支
git revert -m 1  # 撤销合并,回到合并前

# 场景2:想切换主分支到另一个分支
git revert -m 2  # 相当于把主分支变成被合并的分支

查看合并提交的父分支

bash

# 查看合并提交的详细信息
git show <merge-commit-id>
# 输出会显示:
# Merge: def5678 ghi9012
# def5678 是第一个父提交
# g

总结:-m 1 就是告诉 Git "撤销这次合并,但保留合并时当前分支的内容",这是最常用的撤销合并的方式。

二、如何在主分支上撤回所有功能分支A的合并提交

这是一个很常见的需求:主分支上合并了多个功能分支,现在只想撤回功能分支A的所有合并提交,但保留其他功能分支的修改。

核心挑战

功能分支A的提交可能:

  1. 多次合并到主分支(多次merge)
  2. 与其他分支的提交交错在一起
  3. 部分提交可能被其他分支依赖

方法一:使用 git revert + 查找所有合并提交(推荐)

bash

# 1. 找出功能分支A的所有合并提交
git log --oneline --merges main --grep="Merge branch 'feature-A'"

# 或者更精确地查找
git log --oneline --merges main | grep "feature-A"

# 2. 从新到旧依次撤销(注意顺序:从最新到最旧)
git revert -m 1 <最新的合并commit-A>
git revert -m 1 <次新的合并commit-A>
# ...

# 3. 推送
git push origin main