[Git翻译]Git rebase --onto一个概览
从当前分支中删除提交或改变父分支。
原文地址:womanonrails.com/git-rebase-…
发布时间:
在文章《如何在git中改变父分支?》我很快就谈到了当你想替换当前的父分支时,如何使用 git rebase --onto。但 git rebase --onto 不仅仅是替换父分支,我们还可以用 git rebase 做更多的事情。我们可以利用git rebase --onto帮助做更多的事情。这是一个很好的话题,可以仔细看看。要想自如的使用它,首先你要了解它。
有两种情况下,你可以使用 git rebase --onto。
- 你有一个分支,你想改变它的父分支。
- 你想快速从当前分支中删除一些提交。
当然,你可以把这两个原因结合起来。当然,你可以结合这两个原因,既可以改变父分支,也可以同时删除一些提交。我们将到达这一点。但在这之前,我们需要了解 git rebase --onto 与两个参数和三个参数的区别。
让我们从头说起。首先,我们将只关注一个简单的git rebase。我单独写了一篇关于git rebase的文章。所以如果你想了解更多关于git rebase的信息,请去那里。现在,我们将很快地介绍它。
git rebase
git rebase <newparent> <branch>
是一个允许我们访问<newparent>
中最新提交的命令,并将我们的<branch>
提交移到它上面。
如果我们使用以下命令
git rebase master next-feature
我们将得到。
前后
Before After
A---B---C---F---G (HEAD master) A---B---C---F---G (master)
\ \
D---E (next-feature) D'---E' (HEAD next-feature)
如你所见,在git rebase之后,我们的head总是最后一个参数。在我们的例子中,我们的分支是 next-feature。所以我们将分支切换到 next-feature。在这个分支上,我们仍然可以访问提交D和E的代码,但它们不是同一个提交。它们的唯一标识符由加密哈希函数 SHA-1 (dce79fd) 生成,也就是我们常说的 SHA,发生了变化。这就是为什么我把它们标记为D'和E'。
当我们使用git rebase,并且我们已经在我们要重写的分支上,我们可以跳过第二个参数。我们可以这样做
git rebase master
结果也是一样
Before After
A---B---C---F---G (master) A---B---C---F---G (master)
\ \
D---E (HEAD next-feature) D'---E' (HEAD next-feature)
在这两种情况下,主分支上都有两个提交F和G,而这两个提交是无法从下一个特性分支上获得的。当我们进行 git rebase 时,我们将 D 提交(这是下一个特性分支上的第一个提交)与该分支上的所有下一个提交一起,然后将它们移到主分支上的最后一个提交之上,因此移到 G 上。但是,请记住,当你使用git log这样的工具时,你会看到在主分支之上的变化。换句话说,我们把下一个特性分支的父分支从提交 C 改成了主分支上的提交 G。
Git rebase -onto
更精确地改变根分支
在使用 git rebase --onto 时,我们不仅可以将分支的起始点改为父分支的最后一次提交,还可以选择特定的提交点作为起始点和结束点。这不仅在一个特定的分支上是如此,在其他分支上也是如此(所有有效的提交)。我们可以说,git rebase --onto是一个精确而有弹性的解决方案。它可以让你控制哪些内容和哪些地方被重垒。
例如,您想把分支的起点从 C 改为 F,并想从下一个特性分支中删除提交 D。要做到这一点,我们需要使用这个命令。
git rebase --onto F D
效果会是这样的。
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
\ \
D---E---H---I (HEAD my-branch) E'---H'---I' (HEAD my-branch)
我们将从HEAD(我的分支)可到达的提交重新垒起来,其中父提交是D,在F提交之上。所以,我们可以说,我们把提交E的父提交从D改为F。
同样的效果,我们在调用时也会得到。
git rebase --onto F D my-branch(我的分支)
当我们使用最后一次提交的参数而不是HEAD时,情况就不同了。在我们的例子中I.当我们将调用。
git rebase --onto F D I
效果是这样的。
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
\ | \
D---E---H---I (HEAD my-branch) | E'---H'---I' (HEAD)
\
D---E---H---I (my-branch)
和普通的 git rebase 一样,我们将 HEAD 切换到 git rebase --onto 命令的最后一个参数。在本例中,这是一个提交I'。我们看到,我们的分支 my-branch 和之前一样。my-branch没有任何变化。但是我们有了一个新的分支,它是我们新的 HEAD,现在它还不是真正的分支。现在它还不是真正的分支,但我们可以给它起个名字。这里发生了什么?我们告诉 git,我们改变了提交 E 的父分支,你可以想:"但是,为什么要提交 E?我们的命令里没有提交E。" 既然当前的父级是提交D,那么它的子级就是提交E,所以我们把提交E的父级从D改成了F,但是我们也把head从分支my-branch改成了新的提交I'。
同样的效果,我们调用时也会得到。
git rebase --onto F D HEAD
类似的情况是,当我们想把HEAD切换到提交H时,我们将使用命令。
git rebase --onto F D H
我们的分支将是这样的。
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
\ | \
D---E---H---I (HEAD my-branch) | E'---H' (HEAD)
\
D---E---H---I (my-branch)
唯一与上一个例子不同的是,我们没有在提交I'完成新的HEAD,而是在提交H'完成。我们忽略了 HEAD 所指向的位置,我们选择了在旧 HEAD 之前的一个提交 - 提交 H,当我们执行这些命令时,我们将得到等价的行为。
git rebase --onto F D H
git rebase --onto F D HEAD^
git rebase --onto F D HEAD~
git rebase --onto F D HEAD~1
删除当前分支的提交
这是个不错的解决方案。当你想在不使用交互式重垒的情况下,快速删除当前分支的一些提交。如果我们有一个分支,我们想删除提交的 C 和 D,我们可以通过以下方法来实现。
git rebase --onto B D
这给我们。
Before After
A---B---C---D---E---F (HEAD branch) A---B---E'---F' (HEAD branch)
在这个例子中,我们说rebase HEAD在提交B之上,而旧的父分支是一个提交D。
git rebase --onto B D my-branch
如果我们使用 git rebase --onto 时有三个参数,其中最后一个是提交标识符,情况就会略有不同。我们可以说,在提交 B 的基础上重写 HEAD,而旧的父分支是提交 D,但只在提交 E 上重写 HEAD。为此,我们将使用以下命令
git rebase --onto B D E
我们将得到一个只有提交E'和父提交B的新分支。
Before After
A---B---C---D---E---F (HEAD branch) A---B---C---D---E---F (branch)
\
E' (HEAD)
摘要 git rebase -onto
我们来总结一下git rebase --onto是如何工作的。我们可以用两个或三个参数来调用git rebase --onto。当我们使用两个参数时,一般的语法是这样的。
git rebase --onto <newparent> <oldparent>
这将允许将当前的父分支改为新的父分支。因为我们没有指定第三个参数,所以我们会留在当前分支上。对于有三个参数的 git rebase ---onto,情况会有所不同。这是一般的语法。
git rebase --onto <newparent> <oldparent> <until>
现在我们可以将旧的父级改为新的父级,但我们只接受提交,直到提交为止。记住,将在rebase完成后成为新的head。
通过www.DeepL.com/Translator(免费版)翻译
转载自:https://juejin.cn/post/6942933139576586248