You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Feature分支合并回滚后,子特性分支无法合并到Master的原因

Git合并后sub-feature分支变更缺失的原因解析

问题场景

  • 存在2条特性分支:feature-01、feature-02
  • 存在1条子特性分支:sub-feature-01
  • 操作流程:
    1. 将sub-feature-01合并到feature-01,随后回滚该合并操作
    2. 将feature-01合并到master分支
    3. 将sub-feature-01合并到feature-02
    4. 将feature-02合并到master分支
  • 结果:master分支中未包含sub-feature-01的变更

提交历史可视化

*   985c298 (HEAD -> master) Merge branch 'feature-02'
|\  
| *   4f19fd8 (feature-02) Merge branch 'sub-feature-01' into feature-02
| |\  
| * | d568a9f feature-02 commit 1
* | |   14a821c Merge branch 'feature-01'
|\ \ \  
| |/ /  
|/| |   
| * | 2ceae5b (feature-01) Revert "Merge branch 'sub-feature-01' into feature-01"
| * |   1160f07 Merge branch 'sub-feature-01' into feature-01
| |\ \  
| | |/  
| | * 265d0e8 (sub-feature-01) Super-dooper feature
| * | 79b5ad1 feature-01 commit 1
| |/  
* | d8b0552 master commit 2
|/  
* b013ef6 master commit 1
* 2d70803 initial commit

可复现脚本

# 1 - initial commit to master & commit to master
git init
echo "hi from master" > file-master.txt
git add file-master.txt
git commit -m "initial commit"

echo "hi from master - part 2" >> file-master.txt
git add file-master.txt
git commit -m "master commit 1"

# 2 - create super-dooper feature branch
git checkout -b sub-feature-01
echo "this is the feature" > file-sub-feature.txt
git add file-sub-feature.txt
git commit -m "Super-dooper feature"
 
# 2 - create feature-01, commit sth, merge super-dooper feature, and then revert it
git checkout master
git checkout -b feature-01
echo "hi from feature-01" > file-feature-01.txt
git add file-feature-01.txt
git commit -m "feature-01 commit 1"

git merge --no-edit sub-feature-01
git revert --no-edit -m1 HEAD

# 3 - master commit
git checkout master
echo "hi from master - part 3" >> file-master.txt
git add file-master.txt
git commit -m "master commit 2"

# 4 - create feature-02, commit sth
git checkout -b feature-02
echo "hi from feature-02" > file-feature-02.txt
git add file-feature-02.txt
git commit -m "feature-02 commit 1"

# 5 - merge feature-01 to master
git checkout master
git merge --no-edit feature-01

# 6 - reapply merging sub-feature-01 to feature-02
git checkout feature-02
git merge --no-edit sub-feature-01
 
# 7 - merge feature-02
git checkout master
git merge-base master feature-02
git merge --no-edit --stat feature-02

ls # I expected to see  file-sub-feature.txt but it's not here !!!

# git log --all --decorate --oneline --graph

核心原因:Git基于提交可达性判断变更是否已处理

Git的合并逻辑不关注文件内容的变更是否存在,只判断提交是否已经在目标分支的可达历史中:

  1. 当sub-feature-01合并到feature-01后,sub-feature-01的提交(265d0e8)已被纳入feature-01的历史。后续的回滚操作(2ceae5b)只是生成了一个撤销变更的新提交,但原合并提交(1160f07)和sub-feature-01的提交仍然保留在历史里。
  2. 当feature-01合并到master后,master的历史就已经包含了sub-feature-01的所有提交(从master的HEAD往上追溯,能找到265d0e8)。
  3. 合并feature-02到master时,Git会先找到两者的共同祖先(d8b0552),对比从共同祖先到两边的差异。但因为sub-feature-01的提交已经在master的可达历史中,Git会判定这些变更“已经被处理过”——即使回滚操作撤销了内容,Git只认提交存在性,不会检查内容是否有效。因此合并时会跳过sub-feature-01的变更,不会将其重新引入master。

补充说明:回滚合并提交的特殊性

普通的git revert是撤销单个提交的变更,但回滚合并提交时,Git无法直接“取消合并”,只能生成一个反向的变更提交来抵消合并带来的修改。这种情况下,原被合并分支的提交仍然存在于主分支的历史中,后续其他分支再合并该子分支时,Git会认为这些提交已经被合并过,不会重复应用变更。

如果需要重新将sub-feature-01的变更引入master,不能通过合并的方式,而是需要用git cherry-pick将sub-feature-01的提交重新应用到master,或者基于最新的master重新创建sub-feature-01的变更提交。


内容的提问来源于stack exchange,提问作者mzakrze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 09:45:36