0

我认为我的标题不够清楚,所以我将描述问题:

在我的 git 项目中,我有 3 个分支:masterb1b2. 这是历史树:

 A---B---C  master
          \
           D---E---F  b1
                    \
                     G---H---I  b2

假设我想重新设置b1分支并编辑E提交。变基后,提交E并将F被新的提交替换,E'并且F'具有不同的提交 SHA。因此, 中的历史b1将不同于 中的历史b2

 A---B---C  master
           \
             D---E'---F'  b1
                     
 A---B---C---D---E---F---G---H---I  b2

所以我的问题是:如何确保在变基之后b2遵循b1(自动获得与 相同的新提交b1),b1以便它们各自的历史保持一致。

4

3 回答 3

1

在你第一次变基之后,它不是这样的:

 A---B---C  master
           \
             D---E'---F'  b1
                     
 A---B---C---D---E---F---G---H---I  b2

而是这个:

A---B---C  master
         \
          D---Ea---F'  b1
           \      
            E---F---G---H---I  b2

在这里,Ea表示修改后的E提交。如果我理解正确,你想要这个:

A---B---C  master
         \
          D---Ea---F'  b1
                    \      
                     G'---H'---I'  b2

您可以使用交互式变基来实现此目的:

git checkout b2
git rebase -i b1

在 rebase 编辑中,您注释掉提交 E 的行:

# pick df8efe6 E
pick a7fcbed G
pick 936b51a H
pick c77ca69 I

# ...
# Commands:
# p, pick = use commit
# ...
# If you remove a line here THAT COMMIT WILL BE LOST.

回应您的评论,如果您想从起始位置 (ABCDEFGHI) 一直到所需的结束位置:

git checkout b2
git rebase -i master

在编辑器中:

pick 1234567 D
edit a7fcbed E
pick 936b51a F
pick c77ca69 G
pick 1e8d614 H
pick 8daafa7 I

# ...
# p, pick = use commit
# e, edit = use commit, but stop for amending
# ...

完成后,更正b1分支:

git checkout b1
git reset --hard 936b51a

您还可以查看其他答案以获取灵感。我不确定你为什么要在一个命令中实现所有这些;您仍然必须在过程中的某处修改提交 E。它为您节省了一个交互式 rebase 来做到这一点。

于 2020-07-08T18:31:37.293 回答
1

如果您只有两个分支,并且具有如图所示的线性历史记录:

我会变基b2而不是b1

 A---B---C  master
          \
           D---E'---F'
                     \
                      G'---H'---I'  b2

然后更新b1

git branch -f b1 F'

@Han-KwangNienhuys 的答案是完全有效的,如果您需要在已经重写b2时进行更新,您可以应用它。b1

于 2020-07-08T21:37:13.517 回答
0

所以我的问题是:如何确保 b2 遵循 b1(自动获得与 b1 相同的新提交)。

您还需要重写 b2 的历史记录,您正在重新定位所有master..b2提交并重新挂起b1andb2标签。

git branch交互式变基可让您在每一步之后执行任意命令,尤其是包括. 也一样

git rebase -i master b2

并在当前 b1 提交之后的选择列表中说exec git branch -f b1.

你可以自动化这个,通过管道选择列表缓冲区

while read command commit rest; do case $command in 
*) printf %s\\n "$command${commit:+ $commit${rest:+ $rest}}" ;;&
pick) git for-each-ref refs/heads --points-at $commit \
        --format='exec git branch -f %(refname:short)' ;;
esac; done

并且它会exec git branch -f在每次选择分支提示后添加 's。我刚刚构建并尝试了这个。调味,当然。

如果您要深入到分支历史中,最好只构建您想要的确切的樱桃挑选和分支序列;rebase 是一个方便的命令,旨在简化常见任务。像所有好的工具一样,它可以比你想象的更进一步,但它有它的局限性。

于 2020-07-08T23:57:40.753 回答