Git rebase 分支与所有父分支(或依赖子分支)

发布于 2024-08-30 19:23:22 字数 987 浏览 9 评论 0原文

是否可以使用 Git 来对分支及其所有父分支进行变基? (我认为“父分支”是在这里使用的正确形式。根据您的观点,您也可以将它们称为依赖子分支。但是,遵循提交的父指针将让您到达这些分支,所以恕我直言称它们为“父分支”是公平的)。

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

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

现在我想将 rebase -i master 更改为 origin/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

有没有办法解决它,或者我是否坚持重新创建所有父分支(更具体地说是分支标签)都在新的、重新基础的提交上?

这个问题与 Rebasing abranch including all itschildren 相关,但仍然有很大不同

Is it possible to rebase a branch with all its parent branches with Git? (I think "parent branches" is the correct form to use here. Depending on your viewpoint, you might also call them dependent sub-branches. Yet, following the parent-pointers of the commits will get you to those branches, so IMHO it is fair to call them "parent branches").

I often use branches as quick/mutable tags/checkpoints to mark certain commits.
All parent branches/parent refs are fully included in the branch-to-be-rebased; there are no commits only in the parent branches.

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

Now I want to rebase -i master onto origin/master to change/reword the commit featureA-finished^

After git rebase -i --onto origin/master origin/master master, I basically want the history to be:

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

but what I get is:

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

is there a way around it, or am I stuck with recreating all parent branches – more specifically the branch labels – on the new, rebased commits?

This question is related to, but still very different from Rebasing a branch including all its children.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦巷 2024-09-06 19:23:22

看起来这个功能正在慢慢进入 Git。 rebase 将获得选项 --rebase-refs ,它将完全按照我原来的答案要求的操作。对于建议的补丁系列,请参阅线程 rebase: command "ref" and options - gmane 上的 -rewrite-{refs,heads,tags}


2022 年更新:

选项 - -update-refs 终于登陆了 Git v2.38.0,它现在可以完全执行 12 年前最初问题中所要求的操作:)

此功能已与 commit 3d8e3dc4fc22fe41f8ee1184f085c600f35ec76f。万岁!

Looks like this feature is slowly getting into Git. rebase will gain the option --rebase-refs which will do exactly what my original answer asked. For the proposed patch series see the thread rebase: command "ref" and options --rewrite-{refs,heads,tags} on gmane.


Update 2022:

The option --update-refs has finally landed in Git v2.38.0, which can now do exactly what was asked in the initial question more than 12 years ago :)

This feature was merged with commit 3d8e3dc4fc22fe41f8ee1184f085c600f35ec76f in August. Hooray!

Smile简单爱 2024-09-06 19:23:22

根据 git 的 对象模型 如果您只更改提交的元数据(即提交消息)而不是其中包含的基础数据(“树”),那么它的树哈希将保持不变。

除了编辑提交消息之外,您还执行变基,这将更改历史记录中每个提交的树哈希,因为从 origin/master 拉取的任何更改都会影响您的 re- 中的文件。书面历史记录:这意味着您的提交指向的某些文件(blob)已更改。

因此,没有万无一失的方法可以做你想做的事。

也就是说,使用 rebase -i 编辑提交通常不会更改提交的时间戳和作者,因此您可以使用它来唯一标识 rebase 操作之前和之后的提交。

在进行变基之前,您必须编写一个脚本,根据这些“时间戳:作者”标识符记录所有分支起点,然后找到具有相同“时间戳:作者”ID 的重写提交,并在其上对分支进行变基。

遗憾的是,我现在没有时间尝试自己编写这个脚本,所以我只能祝你好运!

编辑:您可以使用以下方式获取作者电子邮件地址和时间戳:

$ git log --graph --all --pretty=format:"%h %ae:%ci"
* 53ca31a [email protected]:2010-06-16 13:50:12 +0100
* 03dda75 [email protected]:2010-06-16 13:50:11 +0100
| * a8bb03a [email protected]:2010-06-16 13:49:46 +0100
| * b93e59d [email protected]:2010-06-16 13:49:44 +0100
|/
* d4214a2 [email protected]:2010-06-16 13:49:41 +0100

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

$ git branch --contains 03dda75
* testbranch

注意每个提交的多个分支,共同祖先< code>d4214a2 属于两个分支!

According to git's Object Model if you only change the meta-data of a commit (i.e. commit message) but not the underlying data ("tree(s)") contained within it then it's Tree hash will remain unchanged.

Aside from editing a commit message, you are also performing a rebase, which will change the Tree hashes of each commit in your history, because any changes pulled from origin/master will affect the files in your re-written history: which means some of the files (blobs) that your commit points to have changed.

So there is no bullet-proof way to do what you want.

That said, editing a commit with rebase -i does not usually alter the commit's timestamp and author, so you could use this to uniquely identify your commits before and after a rebase operation.

You would have to write a script which records all the branch start-points against these "timestamp:author" identifier before doing a rebase, and then find the rewritten commits with the same "timestamp:author" ID and rebase the branch on it.

Sadly, I don't have time to try writing this script myself now, so I can only wish you the best of luck!

Edit: You can obtain the author email address and timestamp using:

$ git log --graph --all --pretty=format:"%h %ae:%ci"
* 53ca31a [email protected]:2010-06-16 13:50:12 +0100
* 03dda75 [email protected]:2010-06-16 13:50:11 +0100
| * a8bb03a [email protected]:2010-06-16 13:49:46 +0100
| * b93e59d [email protected]:2010-06-16 13:49:44 +0100
|/
* d4214a2 [email protected]:2010-06-16 13:49:41 +0100

And you can obtain a list of branches for each of these based on their commit hash:

$ git branch --contains 03dda75
* testbranch

Watch out for multiple branches per commit, the common ancestor d4214a2 belongs to both branches!

背叛残局 2024-09-06 19:23:22

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

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

应该足以用正确的历史记录重置你的 featureA-finished 分支。

I am not sure how exactly you got there, but:

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

should be enough to reset your featureA-finished branch with the right history.

夜巴黎 2024-09-06 19:23:22

我建议首先将 featureA-finished 重新设置为 origin/master 。然后进行改写步骤。之后,将 master 重新设置为 featureA-finished。这将为您带来您想要的最终结果。

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

What I'd advise is to rebase featureA-finished onto origin/master first. Do the rewording step then. After that, rebase master onto featureA-finished. This will net you the end result you are wanting.

Note that you'll need to use -i on both rebases, and may have to delete all the commits from the original featureA-finshed down in the second rebase. If you wanted, you could write a script that would eliminate this by saving off the intermediate branch and using that as the base for a rebase --onto the new version. It could even handle a sequence of such 'subbranches' if you wrote it right. If you need help I can attempt to bang one out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文