需要解释 Git rebase 命令的参数上下文含义

9

很多时候,git rebase 是在某个分支的上下文中使用的。例如,如果我想要将 feature 分支的基础移动到 master 分支的顶部(基于最新提交)- 教程会这样说:

git checkout feature
git rebase master 

在这样的教程之后,会有很多问题。例如:如何在不检出的情况下执行相同的操作?如何使用--onto选项执行相同的操作?--onto和普通rebase之间有什么区别?我可以传递一系列的提交还是必须是整个分支?等等...
我已经多次阅读了man页面,但仍然存在很大的差距。
因此,主要问题是:Git如何解析不同场景中的参数,以及我应该如何在我的头脑中解释/想象它们?例如:
git rebase master
git rebase feature master
git rebase --onto master feature
git rebase HEAD~4 HEAD~2
git rebase --onto HEAD~4 HEAD~2

假设我们有以下仓库:
Z -- W (HEAD, test-branch*) 

A -- B -- C -- D -- E (master)
     \
      1 -- 2 -- 3 (feature)

test-branch is checked out.
2个回答

14

完整的 rebase 命令是这样的。

git rebase --onto <onto> <upstream> <branch-to-rebase>

Git会将branch-to-rebase中那些不在upstream中的所有更改放在onto的顶部。

默认值是...

  • branch-to-rebase:当前分支
  • upstream:branch-to-rebase跟踪分支
  • onto:upstream

git checkout feature; git rebase master实际上是git rebase --onto master master feature

通常希望ontoupstream相同,但有时它们之间有所不同对于精细的操作很有用。这个例子清楚地说明了upstreamonto之间的区别。

           A--B--C--D master
               \
                E--F--G next
                       \
                        H--I--J topic
如果你执行git rebase master topic,它将重新安排所有不与master共有的提交,所有介于两者之间的分支头将被忽略。也就是说,E、F、G、H、I 和 J 的提交将会放到 master 上。由于onto默认为upstream,因此它会将这些提交放在master上。你最终将得到如下结果。
           A--B--C--D master
               \     \
                \     E'-F'-G'-H'-I'-J' topic
                 \
                  E--F--G next

如果你只想要从nexttopic的提交记录,那该怎么办?这就是使用--onto命令很有用的地方。告诉Git上游分支是next,但你想基于master进行变基。因此运行git rebase --onto master next topic。这将选择仅包含H、I和J的提交记录。

           A--B--C--D master
               \     \
                \     H'-I'-J' topic
                 \
                  E--F--G next

非常好!我需要仔细阅读一下。你能解释一下在这个上下文中upstream是什么意思吗?我尝试翻译了一下这个词,但没有得到有用的信息。 - Timur Fayzrakhmanov
2
@TimurFayzrakhmanov upstream 是一个分支所分支出来的源分支。upstream 就像逆流而上的河流。这里的水流代表时间。如果你开始沿着历史记录向另一个分支走回去,那么你就是在向上游走。在我的例子中,mastertopic 的上游。对于 rebase 而言,Git 会将 branch-to-rebase 中所有不在 upstream 中的更改放在 onto 的顶部。 - Schwern

1

git rebase手册页面

  • git rebase master将当前分支变基在master之上(意味着master被检出,当前分支被重置为master,它的提交被变基在其之上)。

假设当前分支是test-branch:

A -- B -- C -- D -- E -- Z' -- W' (test-branch)
                 (master)
  • git rebase feature mastermaster 的提交记录重放在 feature 上方(这种情况很少见,最佳实践是相反的)

也就是说:

A -- B
      \
       1 -- 2 -- 3 -- C' -- D' -- E' (master)
              (feature)
  • git rebase --onto master feature 会将特性分支之后的所有提交移动到新基础 master 上当前分支的顶部。
    由于 featuretest-branch 不相关,因此不会移动任何提交。

  • git rebase HEAD~4 HEAD~2 将当前分支重置为 @~2

对于像 Z -- Y -- X -- W 这样的 test-branch,这意味着 Z -- Y

  • git rebase --onto HEAD~4 HEAD~2 将从 @~2(即 @~1@)之后的所有提交重新应用到新基础 @~4 上,因此会删除当前分支中的 @~3@~2 的提交。

很遗憾,@VonC,但是我没有理解你从第二个例子开始的想法。我无法想象没有模式发生了什么(如果您能像第一个示例那样提供模式,我将不胜感激)。 - Timur Fayzrakhmanov
1
@TimurFayzrakhmanov,我只为第二种情况添加了一个图表。 - VonC

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