Git rebase 和子分支

17

我有以下情况存在于我的项目中

Master M1----M2----M3----M4----M5
                     \
                 Beta B1----B2----B3---B4
                                   \
                          Feature   F1---F2---F3

我正在开发 Feature,但是在提交 M5 上发布了一个非常重要的更新,我不想将 FeatureB3 分离开来(Feature 依赖于 B1B2),并且 Beta 可以有这个更改(对于 Beta 没有区别)。

如果我在 Beta 上做一个 git rebase Master,那么它只会移动 Beta 分支,对吗(没有应用到 Feature 上的任何更改)?还是最终会变成这样(下面 - 更改也应用到 Feature 上了)?

Master M1----M2----M3----M4----M5
                                 \
                             Beta B1----B2----B3---B4
                                               \
                                      Feature   F1---F2---F3

那么,要达到这样的效果(应用于Feature),我应该怎么做呢?那就是我期望的状态...


  1. 没错,对 Beta 的操作不会影响到 Feature
  2. 直接在 Feature 分支上进行变基。
- 0andriy
2个回答

29

你是正确的:在 Beta 分支上运行 git rebase Master 不会影响 Feature 分支。(顺便问一句:为什么要大写字母?)

这里的根本问题在于,git rebase 的含义是“复制一些提交”。关键在于看哪些提交被复制到了哪里,以及分支名称在此之后会发生什么变化。如果被复制的提交还可以从其他某个分支访问到,则复制前的原始提交仍然可以从那个分支访问到。

请记住,所有分支名称只是指向分支上最新提交的指针。即使那些早期的父提交也在该分支上,即使那些早期的提交也在其他分支上。因此,“所有 Beta 提交”最初包括 M1M3

那么,第一个 git rebase 是如何知道仅复制 B1B2B3B4 的呢?我认为其中一个关键是稍微改变一下图形:

M1----M2----M3----M4----M5   <-- Master
              \
               B1----B2----B3---B4   <-- Beta
                            \
                             F1---F2---F3   <-- Feature

要查看将要复制的内容,请使用绿色荧光笔标记分支的最后提交,即Beta所指向的B4,并在沿着向左的线条跟随时将所有提交都标记为绿色,包括提交M3及更早的提交。然后,将红色荧光笔用于Master的最后提交(即M5),并在沿着向左的线条跟随时将所有提交都标记为红色。红色涂覆盖了绿色,因此不考虑M3及更早的提交进行复制。这正好留下正确的提交集进行复制。

复制本身位于参数的最后提交之后。那是Master,因此复件在M5之后。

Git完成复制后,Git将名称Beta移动到B4的副本所指向的位置,我们将其称为B4'。这样可以保留原始的Bn提交,但是除了B3可以从F1访问外,所有提交都被悬挂了。

                          B1'---B2'---B3'--B4'   <-- Beta
                         /
M1----M2----M3----M4----M5   <-- Master
              \
               B1----B2----B3---B4   [no name]
                            \
                             F1---F2---F3   <-- Feature

所以对于 Beta 来说一切都很好,但现在你想复制 Feature 的提交记录。如果您:

git checkout Feature
git rebase Beta

Git会将F3标记为绿色,然后是F2F1……但接下来还会将B3B1的内容也标记为绿色。只有副本B1'B2'B3'B4'以及五个M提交会被标记或覆盖为红色。所以Git会复制过多的提交。

解决方案是使用git rebase --onto <name>命令。添加--onto参数告诉Git在哪里放置这些副本:你希望它们放在B4'之后,所以可以使用--onto Beta命令,表示这些副本应该放在Beta之后,也就是B4'之后。

这实际上并没有真正解决任何问题…… 但它释放了另一个参数,即原来的Beta参数,现在可以用来代替其他内容。

你需要告诉Git从哪里开始标记提交为红色,这个点是B3,或者更容易理解的是B4。这将会把B3和它之前的所有提交(包括M3以及之前的提交)标记为红色:不要复制。

你可以使用B3的原始ID,如果你保存了它的话。或者,你可以轻松地让Git使用Beta@{1}查找Beta的上一个终点:

git rebase --onto Beta Beta@{1}

使用 Beta 的 reflog,找到提交 B4 的哈希 ID。

Translated sentence:

使用 Beta 的 reflog,找到提交 B4 的哈希 ID。


解说得很清楚。如果段落“Git will color…”中的“copies”意味着B1'B2'B3'B4',那应该更清晰明了。 - randvir
@randvir:它表达了我的意思,但我同意它可以稍微改进一下。我现在尝试着做了一些修改。 - torek

1
实际上,最终会得到类似于这样的东西:
Master M1----M2----M3----M4----M5
                    \            \
                     \       Beta B1----B2----B3---B4
                      \
                       \--B1'---B2'---B3'----F1---F2---F3
                                                       ^
                                                    feature

基本上,你对于 Beta 的变基将会在当前主分支的顶部重新应用 Beta 上的提交。然而,原始提交仍将存在,如果其他内容(例如另一个分支)引用了这些提交,则它们仍将持续存在。

你需要首先变基 Beta,然后再变基 feature才能将所有内容“移动到正确的位置”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接