Git:使用自动选择功能将标签从一个分支复制到另一个分支

时间:2018-12-19 18:21:49

标签: git tags cherry-pick

我有一个MASTER分支,其中包含多个提交和标签。我只想将标签从MASTER复制到RELEASE分支中(而无其他提交)。

我首先创建了一个空的MASTER分支,并仅通过消息提交了它。然后,我创建了一个空的RELEASE分支。我向MASTER添加了一些提交,内容如下:

  • C1:文件1
  • C2:file1,file2
  • C3:file1,file2,file3

在MASTER中,我使用C2创建了标签T1(其中包含file1和file2)。现在,我想将标签T1复制到RELEASE分支。看来我需要用樱桃摘来做这个。

我首先注意到MASTER中标签T1的SHA-ID。然后我这样做:

  • git checkout发布
  • git cherry-pick [T1的SHA-ID]

成功,但是RELEASE分支现在仅显示file2。它不应该显示标签T1的内容,即文件1和文件2吗?

同样,我的目标是只在RELEASE中显示MASTER的标签(没有其他提交)。这可能吗?预先感谢。

1 个答案:

答案 0 :(得分:0)

让我们从这里开始:

  

...我的目标是仅在RELEASE中显示来自MASTER的标签(而没有其他提交)

这个目标在Git中毫无意义。在Git中,所有参考名称都在提交集合的外部中。而且,名称之间没有容器/包含的关系(具有一个约束,该约束是从Git当前实现这些名称的方式继承的)。也就是说,名称AB彼此完全独立。名称feature/Xfeature/Y也彼此完全独立。进行任何更改(包括创建新名称或删除旧名称)都不会影响其他任何名称。

(这里的例外是,一旦您拥有名称feature/Xfeature/Y,就不能再使用名称feature。该名称现在被“占用”了。其他两个名称中的feature/部分。您可以继续使用feature/保留更多名称,并且可以使用featur而不使用最后一个e,但是您不能创建名称feature来标识对象,因为feature/由于feature/X和/或feature/Y而存在。)

标记名称不包含在分支中。分支名称不包含在标签中。它们都是独立的实体,彼此并存。由您来组织它们。一种明智的方法是使用这些斜杠:feature/name是您和/或其他人正在开发其名称(或代号)为 name的新功能的分支的好简称。 。形式为relbranch/name的分支名称可能是用于组织将提交到特定发行版中的提交(名称(或代码名称)为 {name )的提交的很好的短名称。当针对某个特定版本的特定提交已通过质量检查验证,并且现在已经发货时,releases/name形式的标记名称可能是该版本的好简称。

(请注意,git for-each-ref是用于处理引用的内部Git命令,对斜杠分隔的名称组件特别满意:git for-each-ref refs/tags/releases遍历refs/tags/releases/*中的所有标签,例如。)

有关标签和分支名称的更多信息

标签只是指向提交的指针。也就是说,每个提交对象都有其自己的“真实名称”,这是一个非常丑陋的哈希ID,例如5d826e972970a784bd7a7bdf587512510097b8c7。该名称对于此一次提交是唯一的(这是G​​it在Git存储库中的提交,因此,除非您拥有Git的Git存储库,否则您将不会进行此提交)。 Git用来访问对象的这些真实名称对人类而言并不笨拙且无用,因此Git为我们提供了名称。您可以将标签名设为v2.20.0,其主要功能(有时是两个这样的功能之一)是它取代了记住5d826e972970a784bd7a7bdf587512510097b8c7的需要。

分支名称也是如此,但有两个重要区别:

  • 分支名称预计会随时间更改。也就是说,在提交提交C1之后(无论其实际的哈希ID是什么),名称master是提交C1的名称。但是,随后在master上进行提交C2的动作更改了名称master以现在命名提交C2。当您制作C3时,Git再次更改了master,以便它现在可以识别提交C3。

  • 标签名称应为常数。也就是说,如果您创建的标签 T 命名为提交C2,则每个地方的每个Git -嗯,您曾经直接或间接连接到Git存储库的每个Git存储库-从现在开始可以假设 T 的意思是“提交C2”。如果您在存储库中删除标签 T 并创建一个名称为C3的新 T ,则所有 other Git存储库都是正确的继续将名称​​ T 转换为C2。 (如果更改为C3,它们也是正确的,但不需要转换。)

  • 允许
  • 标记名称通过标记对象间接指向 进行提交。 Git将这种标签称为带注释的标签。标签对象可以存储一些额外的信息,例如PGP签名密钥说 I(签名者)已经检查了该特定提交是否有效,应该使用。 {{1 }}在Git的Git存储库中,例如:

    v2.20.0

    (带注释标签的对应物是 lightweight标签,它仅直接指向提交。默认情况下,$ git cat-file -p v2.20.0 object 5d826e972970a784bd7a7bdf587512510097b8c7 type commit tag v2.20.0 tagger Junio C Hamano <gitster@pobox.com> 1544329907 +0900 Git 2.20 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE4fA2sf7nIh/HeOzvsLXohpav5ssFAlwMmrMACgkQsLXohpav 5sv6pg//VIRzIkTz+DQ4ITzWXpH41lGjhsbSN554a/Kj5W1RvHiQmzpv5HDM65vr Dr9DqYiP3HBOPElUTxT5iS2qgsajrRZ1yvKMEnb+YxLbix0NhkvdhJxHmsTUYmEH SOve1ddx9spKHEdRjgw6eyoTiG5yQgcea7XkdATeTYeJzZIfMcrXVR920ZjUi9dK DRambd/KGYFIPftN0EdVCVPUDrNlKvmK3RhS7arZUxFBxSGDVzGiStK0r2aSw0lb gT27Ygy+cz0StWL2q4kV4ghPhjpAv9QqypNNADRg9ZxDhY446V2flU67oV0PLCm/ E4GmgkjGOphQOujWJv6Uz+6F4E1DvGx9Wt78Xbl3kXZruyhwIv/7yk53nUPxtaI5 PjBqy+2vJPmZoUONH3/zSYlGW4ZwURatXTDe3FOK15Eq3EV+IpbRGhpuu4Ju9U3c L1dpTFdauiKJFuSNkrsdrJPhpX2nbgYl3PloxHWAhPzoqFGib4reRqrm12lczpRp BytNhs8RWwR+4CZXAFYtITFEdBLhHvWodklYnGfTFlMKs/OZ4S+XNS2LOb6Wjc3S EFF4U87QGnHm6vCREpKwVOMroAEOUXsrbHc3tzxrX16GlXHNWYI/fgAkD6twffE8 GEIclUQ7v/fRFlmznDJKGOoWVDTUzwLCVeb36lmpd6w+CpRm7cc= =1E0P -----END PGP SIGNATURE----- 忽略轻量标签,仅使用带注释的标签并使用更人性化的名称来表示某些原始提交哈希。)

由于分支名称移动,因此在您希望人们使用并使用旧名称的新值的情况下,应 使用它们。因为标签名称​​不会移动,所以在您希望人们永远使用一个特定提交的任何情况下,都应使用它们 。由于带注释的标签可以提供对数字签名的访问,因此它们也适用于这些情况。

关于摘樱桃

请注意,git describe 确实执行复制提交。为此,它首先将提交转换为变更集。 (这种解释有点费劲,而忽略了通过合并机制实现“樱桃拾取”的事实,但是足以考虑问题。)请记住,提交保存了 snapshot 每个文件,以您(或任何人)进行提交时的格式保存。

按原样复制提交是不好的。例如,假设您要对旧版本进行相同的 change (修复)操作,而旧版本也将转换为新版本。采用新版本的固定提交(快照)并将其直接复制到旧版本分支中,将使旧版本的下一个版本与新版本的固定提交100%相同,而不仅仅是导入一个修订。因此,cherry-pick根本不会复制快照

要将提交(快照)转换为变更集,Git必须将提交与其直接的前任进行比较。例如,C3的前身是C2,因此通过将C2中的快照与C3中的快照进行比较,Git可以告诉您从C2到C3发生了什么更改

然后,要进行选择,首先要检查一些现有的提交(当然不是C2或C3)。通常,这可以通过git cherry-pick使用开发此特定版本的分支名称来进行。然后,您告诉Git:首先,找出C3中相对于C2 发生了什么变化。然后对我当前的非C2非C3提交进行相同更改,并使用结果进行新的提交。

进行了一次新提交(获得新的大的丑陋哈希ID,不同于其他所有提交的大丑陋的哈希ID),Git像往常一样将新提交的哈希ID写入当前分支名称。现在,无论您使用的是什么分支名称-可能不是git checkout name,而是由您自己决定的-引用此新快照。您可以创建一个 new 标记以指向此新提交,但是由于人们(和软件)期望标记不会更改,因此删除 any 现有标记并替换通常是不明智的带有相同名称的新标签,指向不同的提交。