让我们从这个开始:
...我的目标只是在 RELEASE 中显示来自 MASTER 的标签(而不是其他提交)
这个目标在 Git 中毫无意义。在 Git 中,all 引用名称存在于提交集之外。此外,名称之间没有容器/包含关系(一个约束继承自 Git 当前实现这些名称的方式)。也就是说,名称A 和B 完全相互独立。名称feature/X 和feature/Y 也完全相互独立。进行任何更改(包括创建新名称或删除旧名称)都不会影响任何其他名称。
(这里的例外是,一旦你有了名字feature/X 或feature/Y,你就不能再使用名字feature。这个名字现在被feature/ 部分“占用”了其他两个名字。你可以继续使用feature/来保存更多的名字,你可以使用featur没有最后的e,但是你不能创建名字feature来标识一个对象,因为feature/是存在的因为feature/X 和/或feature/Y。)
标签名称不包含在分支中。分支名称不包含在标签中。它们都是独立的实体,彼此并存。由你来组织它们。一种明智的方法是使用这些斜杠:feature/<em>name</em> 是一个不错的短名称,用于表示您和/或其他人正在开发名称(或代号)为 name 的新功能的分支. relbranch/<em>name</em> 形式的分支名称可能是组织将进入特定版本的提交的好短名称,其名称(或代码名称)为 name。当针对某个版本的某个特定提交已通过 QA 验证并正在交付时,releases/<em>name</em> 形式的标签名称可能是该版本的一个很好的短名称。
(请注意,git for-each-ref,通常用于处理引用的内部 Git 命令,对斜杠分隔的名称组件特别满意:例如,git for-each-ref refs/tags/releases 遍历 refs/tags/releases/* 中的所有标签。)
关于标签和分支名称的更多信息
标签只是提交的指针。也就是说,每个提交对象都有自己的“真名”,也就是像5d826e972970a784bd7a7bdf587512510097b8c7这样的大丑hash ID。此名称对于这一提交是唯一的(它是 Git 存储库中的一个提交,因此除非您有 Git 的 Git 存储库,否则您将不会拥有这一提交)。 Git 用来访问对象的这些真名对人类来说既笨拙又无用,因此 Git 为我们提供了名称。您可以创建一个像v2.20.0 这样的标签名称,它的主要功能——或者有时是两个这样的功能之一——是它取代了记住5d826e972970a784bd7a7bdf587512510097b8c7 的需要。
分支名称也是如此,但有几个重要区别:
预计分支名称会随着时间的推移更改。也就是说,在您提交 C1 之后(无论它的实际哈希 ID 是什么),名称 master 就是提交 C1 的名称。但是随后在master 上进行提交C2 的行为,更改名称master 现在将名称提交C2。当你创建 C3 时,Git 再次更改了 master,以便它现在识别提交 C3。
tag 名称应保持不变。也就是说,如果你创建一个标签 T 来命名提交 C2,每个 Git 无处不在——嗯,你曾经直接或间接连接到你的 Git 存储库的每个 Git 存储库——从现在开始,可以假设 T 的意思是“提交 C2”。如果您在您的存储库中删除标签 T 并创建一个名为 commit C3 的新 T,那么所有 other Git 存储库都是正确的,如果它们继续将名称T翻译成C2。 (换成C3也是正确的,但不需要换过来。)
-
标签名称可以通过标签对象间接指向提交。 Git 将这种标签称为带注释的标签。标签对象可以存储一些额外的信息,例如 PGP 签名密钥,表示 我,签名者,已经检查了这个特定的提交是有效的并且应该被使用。v2.20.0 就是这种情况。例如,在 Git 的 Git 存储库中:
$ 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 忽略轻量级标签,只使用注解的标签一些原始提交哈希的更人性化的名称。)
因为分支名称会移动,它们应该用于您希望人们选择并使用旧名称的新值的任何情况。因为标签名称不会移动,所以它们应该用于您希望人们永远使用一个特定提交的任何情况。因为带注释的标签可以提供对数字签名的访问,所以它们也适用于这些情况。
关于樱桃采摘
请注意,git cherry-pick 会 复制提交。为此,它首先将提交转换到更改集。 (这个解释有点手动,忽略了cherry-pick 是通过合并机制实现的这一事实,但足以考虑这些问题。)请记住,提交保存了一个 snapshot每个文件,以您(或任何人)提交时的形式。
按原样复制提交并不好。例如,假设您想对同样进入新版本的旧版本进行相同的更改(修复)。获取新版本的固定提交(快照)并将其直接复制到旧版本分支中,将使旧版本的下一个版本与新版本的固定提交 100% 相同,而不仅仅是导入一个修复。所以cherry-pick根本不会复制快照。
要将提交(快照)转换为变更集,Git 必须将提交与其直接前任进行比较。例如,C3 的前身是 C2,因此通过将 C2 中的快照与 C3 中的快照进行比较,Git 可以告诉您从 C2 到 C3 的变化。
然后,要进行挑选,首先要检查一些现有的提交(当然 C2 或 C3 除外)。通常,这将通过git checkout <em>name</em> 使用,使用正在开发此特定版本的分支的名称。然后你告诉 Git:首先,弄清楚 C3 相对于 C2 有什么改变。然后对我当前的非 C2 非 C3 提交进行相同的更改,并使用结果进行新的提交。
在进行了一个新的提交之后——它得到了一个新的又大又丑的散列 ID,与其他所有提交的大丑散列 ID 不同——Git 像往常一样将新提交的散列 ID 写入当前分支名称。现在,您现在使用的任何分支名称(可能不是master,但这取决于您)指的是这个新快照。您可以创建一个 new 标签来指向这个新的提交,但是因为人们(和软件)希望标签不会改变,所以删除 any 现有标签并替换通常是不明智的它带有一个同名的新标签,指向不同的提交。