使用Git rebase命令合并所有父分支(或依赖的子分支)到当前分支

19

是否可以使用Git rebase操作将一个分支及其所有父分支合并?(我认为“父分支”是这里要使用的正确表述。根据您的观点,您也可能称它们为依赖子分支。然而,遵循提交的父指针将带您到这些分支,所以在我看来将它们称为“父分支”是公平的)。

我经常使用分支作为快速/可变的标签/检查点来标记某些提交记录。所有父分支/父引用都完全包含在将要重新基于的分支中;没有仅存在于父分支中的提交记录。

* master
*
* featureA-finished
*
* origin/master

现在我想要将master分支rebase -iorigin/master上,以改变/重新命名提交记录featureA-finished^

执行git rebase -i --onto origin/master origin/master master后,我希望历史记录基本上如下:

* master
*
* featureA-finished
* (changed/reworded)
* origin/master

但是我得到的是:

* master
*
* (same changeset as featureA-finished)
* (changed/reworded)
| * featureA-finished
|.* (original commit i wanted to edit)
* origin/master

有没有绕过这个问题的方法,或者说我只能在新的变基提交上重新创建所有父分支-更具体地说是分支标签吗?

这个问题与变基包括其所有子级的分支相关,但仍然非常不同。


1
你可以使用 git notes 来标记你的提交,而不是使用分支 - 在变基过程中,这些标记会自动复制。我相信这是一个新功能,所以你需要最新的版本。http://www.kernel.org/pub/software/scm/git/docs/git-notes.html - Cascabel
请参见如何将整个子历史记录(包括几个分支和由合并产生的某些链接)进行变基。该解决方案的不愉快之处在于需要在变基后将主题分支引用重置为新的变基提交。 - imz -- Ivan Zakharyaschev
4个回答

7

1
很遗憾,这似乎没有进入Git:我在当前的git-rebase文档(manpage)中没有看到这样的功能!(git-1.7.9.3) - imz -- Ivan Zakharyaschev

5
根据git的Object Model,如果您只更改提交的元数据(即提交消息),而不更改其中包含的基础数据(“树”),则其树哈希将保持不变。
除了编辑提交消息外,您还执行了一个rebase操作,这将更改历史记录中每个提交的树哈希,因为从origin/master拉取的任何更改都会影响您重写的历史记录中的文件:这意味着某些文件(blob)指向的内容已经发生了改变。
因此,没有一种绝对可靠的方法可以实现您想要的操作。
话虽如此,使用rebase -i编辑提交通常不会更改提交的时间戳和作者,因此您可以在rebase操作之前和之后使用它来唯一标识您的提交。
您需要编写一个脚本,在做rebase之前记录所有分支起点与这些“timestamp:author”标识符,并找到具有相同“timestamp:author” ID的重写提交并在其上进行分支rebasing。
不幸的是,我现在没有时间尝试编写这个脚本,所以我只能祝您好运! 编辑: 您可以使用以下代码获取作者的电子邮件地址和时间戳:
$ git log --graph --all --pretty=format:"%h %ae:%ci"
* 53ca31a robert.meerman@gmail.com:2010-06-16 13:50:12 +0100
* 03dda75 robert.meerman@gmail.com:2010-06-16 13:50:11 +0100
| * a8bb03a robert.meerman@gmail.com:2010-06-16 13:49:46 +0100
| * b93e59d robert.meerman@gmail.com:2010-06-16 13:49:44 +0100
|/
* d4214a2 robert.meerman@gmail.com:2010-06-16 13:49:41 +0100

您可以根据提交哈希值获取每个分支的列表:

$ git branch --contains 03dda75
* testbranch

注意提交中的多个分支,公共祖先d4214a2属于两个分支!


2

我不确定你是如何到达那里的,但是:

git branch -f (same changeset as featureA-finished)

这应该足以重置您的 featureA-finished 分支并恢复正确的历史记录。


是的,这就是我所说的“在新的变基提交上重新创建分支”的意思。我知道这种方法是可行的,但对于已经有三个分支的情况来说,它变得非常麻烦。 - knittl
1
@knittl:有趣。在此之前和之后,这些分支的更详细的日志图可能会有所帮助。 - VonC
想象一下,同样的图表有15个提交,每隔一秒就会完成一个功能A、功能B、功能C等。 - knittl

1

我的建议是首先将featureA-finished变基到origin/master。然后进行重命名步骤。之后,将master变基到featureA-finished。这将得到您想要的最终结果。

请注意,您需要在两个变基上使用-i,并且可能需要在第二个变基中删除原始featureA-finshed下的所有提交。如果您愿意,可以编写一个脚本来消除这个问题,通过保存中间分支并将其用作重新基于新版本的--onto的基础。如果你写得好,它甚至可以处理一系列这样的“子分支”。如果需要帮助,我可以尝试解决这个问题。


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