了解和记住git rebase参数


12

到目前为止,git最令人困惑的部分是重新部署到另一个分支。具体而言,令人困惑的是命令行参数。

每次我想将一个分支的一小部分重新建立到另一个分支的尖端时,我都必须查看git rebase文档,这大约需要5到10分钟的时间来理解这三个主要参数的含义。

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

有什么好的经验法则可以帮助我记住给任何其他基础重新设置到另一个分支时应将这三个参数分别设置为什么?

请记住,我已经一遍又一遍又一遍(一遍又一遍)遍历了git-rebase文档,但是它总是很难理解(像无聊的科学白皮书之类的东西)。因此,在这一点上,我觉得我需要让其他人参与以帮助我掌握它。

我的目标是,我永远都不必阅读这些基本参数的文档。到目前为止,我还无法记住它们,而且我已经做了很多调整工作。因此,到目前为止,我已经能够记住其他所有命令及其参数,但是却没有使用rebase进行存储,这有点不寻常--onto


您可以为常用用例定义一些git别名,也可以调出一个向导脚本来提醒您每个参数在执行命令之前的含义。
罗里·亨特

4
啊,这些令人赞叹的git命令选项纯属优雅。如此直观地使用。永远是一种真正的乐趣。
JensG 2014年

Answers:


10

让我们--onto暂时跳过。 upstream并且branch是非常基本的,并且实际上是模仿的,checkout并且branch-第二个参数是可选的:

git branch <newbranch>
git branch <newbranch> <base>
git checkout -b <newbranch>
git checkout -b <newbranch> <base>
git rebase <upstream>
git rebase <upstream> <branch>

(题外话,在这些参数的名字rebase,“上游”和“分支”不是很描述性IMO我通常觉得他们像peachoftree。<start>而且<end>,这是我将如何使用它们: git rebase <start> <end>

当省略第二个分支时,结果几乎与先签出该分支然后再执行该操作几乎一样,就像您没有指定该分支一样。唯一的例外是branch不会更改您当前的分支:

git checkout <base> && git branch <newbranch> && git checkout <previous_branch>
git checkout <base> && git checkout -b <newbranch>
git checkout <end>  && git rebase <start>

至于了解rebase调用时的作用,我首先将其视为一种特殊的合并类型。它不是真的,但是在刚开始了解变基时会有所帮助。借用peachoftree的示例:

A--B--F--G master
    \
     C--D--E feature

一个git merge master结果是:

A--B--F-----G master
    \        \
     C--D--E--H feature

虽然git rebase master(在分支上feature!)导致以下结果:

A--B--F--G master
          \
           C'--D'--E' feature

在这两种情况下,feature现在都包含来自master和的代码feature。如果您未打开feature,第二个参数可以用作快捷方式切换到它: git rebase master feature将执行与上述相同的操作。


现在,特别--onto。要记住的重要部分是,<start>如果未指定,则默认为。因此,在上面,如果我--onto特别指定,将导致相同的结果:

git rebase --onto master master
git rebase --onto master master feature

(我不会--onto不加说明<end>就使用,因为这样更容易进行心理分析,甚至认为这两个如果已经启用就相同feature)。

要查看为什么--onto有用,这是一个不同的示例。假设我打开feature并发现了一个错误,然后我开始修复该错误-但它是分支出来的,feature而不是master由于错误而引起的:

A--B--F--G master
    \
     C--D--E feature
            \
             H--I bugfix

我想要的是“移动”这些提交,bugfix以使它们不再依赖于feature。实际上,此答案中上面显示的任何类型的合并或变基都会将三个feature提交与两个bugfix提交一起使用。

例如,git rebase master bugfix是错误的。范围<start><end>恰好包括所有从提交feature,这是对的顶部重播master

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

我们真正想要的是从featurebugfix重播的提交范围master。这就是--onto它的用途-指定与“开始”分支不同的“重播”目标:

git rebase --onto master feature bugfix

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

1

重提一下,重定基调主要用于以下情况:如果两个分支相互独立地发展,则您希望提交历史显示为线性时,基本上可以重写提交历史。

我喜欢这样做的方式是 git rebase --onto <target branch> <start branch> <end branch>

<target branch>您要重新建立基础的分支在哪里,<start branch>通常是从其<end branch>拆分<end branch>的分支,也是您重新基础的分支。

如果你开始

A--B--F--G master
    \
     C--D--E feature

并做

git rebase --onto master master feature

你会得到

A--B--F--G master
          \
           C'--D'--E' feature

要知道的另一件事是,<target branch>默认设置为,<start branch>因此您可以执行与

git rebase --onto master feature

如果您需要更多帮助,请查看“ 重塑基础”指南


您的结果看起来具有误导性。重新设置应该master保持分支本身不变。你只得到“功能”分支出来一样G--C'--D'--E',同时master仍处于停止G
2014年

@Frank,我这样做是为了强调整个线性历史记录,但是现在我认为您的方法会更好。固定。
peachoftree 2014年

1
您能否举例说明不同之处<target branch><start branch>不同之处,以帮助读者理解最一般的情况?
Rufflewind
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.