gpt4 book ai didi

git - 为什么 rebased commit ids 不同于 cherry-picked ids?

转载 作者:太空狗 更新时间:2023-10-29 14:31:53 24 4
gpt4 key购买 nike

这个问题源于一个令人讨厌的小 merge 冲突,当我不小心从我的跟踪分支中挑选到我的跟踪分支而不是 rebase 时,我自己陷入了这个冲突。修复它很容易,但我仍然想弄明白为什么它首先会被发布。

假设我有以下分支( tracking 基于 tracked ),其中包含一系列提交,括号中包含散列,箭头指向父提交。

tracked: a(123) <- b(234) <- c(345)

tracking: a(123) <- b(234) <- c(345)

假设一个新的提交 d 提交 id 为 456 进入 tracked 分支状态如下:

tracked: a(123) <- b(234) <- c(345) <- d(456)

tracking: a(123) <- b(234) <- c(345)

我现在 cherry-pick 456tracking 导致以下跟踪状态:

tracking: a(123) <- b(234) <- c(345) <- d(somethingnot456)

但是,如果我只是执行一个 git rebase tracked,它会是:

tracking: a(123) <- b(234) <- c(345) <- d(456)

那么为什么上面的 id 不同呢?

我已经看到很多关于 rebasecherry-pick 的问题,但我还没有找到这个特定问题的答案。谢谢。

最佳答案

Rebase 和(重复的)cherry-pick 本质上是同一件事,但它们不是 100% 完全同一件事。在这种特殊情况下,关键是被复制的内容,嗯,什么也没有。

让我按照我更喜欢表达 Git 图片段的方式重新绘制您的示例。而不是:

tracked: a(123) <- b(234) <- c(345)

tracking: a(123) <- b(234) <- c(345)

让我们把它画成:

A(123) <- B(234) <- C(345)   <-- tracking, tracked

因为,毕竟,每次提交都是独一无二的:只有一份 A 副本,一份 B 副本,一份 C 副本,很快就会成为一份 D 副本。同时,两个标签( trackingtracked )都指向提交 C ,其散列为 345whatever

现在您将新的提交 D(456) 添加到 tracked(所以 tracking 仍然指向 C(345) :

A(123) <- B(234) <- C(345)          <-- tracking
\
D(456) <-- tracked

cherry-pick 总是复制

git cherry-pick <commit> 所做的本质上是:

  1. 将给定的提交与其父提交进行比较(因此,DC)
  2. 在当前分支 (tracking) 上应用相同的更改,然后
  3. 使用相同的消息但不同的 ID 进行提交。

这当然是您之前看到的。您当前的分支 ( tracking ) 获取新提交 D' :D 的副本,但编号不同。

Rebase 查找哪些提交需要被复制

另一方面,Rebase 通过获取当前分支 ( tracking ) 拥有的所有提交列表来工作,而您的 <upstream> 分支 ( tracked ) 没有。具体来说,这些是 git rev-list 将列出的提交:

$ git rev-list tracked..tracking
$

没有这样的提交,从图中很容易看出这一点。我们甚至不需要哈希:

A <- B <- C     <-- tracking
\
D <-- tracked

tracking 开始,我们按照标记提交的箭头向左工作,但是从 tracked 开始,我们再次按照箭头和取消标记提交的方式向左工作。由于 D 会返回到 C ,这会取消标记所有内容,我们根本不会复制任何内容。

如果我们在 tracking 上有一个没有被跟踪的提交:

A--B--C--E   <-- tracking
\
D <-- tracked

然后 rebase 会复制 E ,创建一个新的(不同的 ID)提交 E'E 的副本将放在 D 之后,如下所示:

A--B--C--E   <-- tracking
\
D <-- tracked
\
E' [rebase in progress]

然后,rebase 移动分支标签

一旦 git rebase 完成所有复制,它会记下它停止的位置——在 D ,如果没有要复制的东西;在 E' ,甚至可能是 F'G' 或任何地方,如果有 提交复制——然后它剥离旧的分支标签 ( tracking ) 并将其粘贴到新点上:

A--B--C--E   [abandoned]
\
D <-- tracked
\
E' <-- tracking

当没有要复制的 E 时,我们会得到这个:

A--B--C
\
D <-- tracked, tracking

也就是说,两个分支标签现在都指向提交 D ,根本没有被复制。 (也没有理由保留图中向下的小腿,也没有要放弃的提交——放弃 E 不会放弃 C ,因为 C 可以从 D 中找到。)

关于git - 为什么 rebased commit ids 不同于 cherry-picked ids?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38446493/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com