将信息存储在分支(元数据)中,关于哪个点与“父”分支分开

问题描述 投票:1回答:1

说我有这个:

latest_commit=`git rev-parse HEAD`
git checkout -b "foo_$latest_commit"
git reset --soft "origin/dev"

我正在做的是跟踪第二个分支从第一个分支偏离的位置。但是没有将提交ID放在第二个分支的名称中,有没有办法在第二个分支的某处存储元数据,所以我不必在分支的名称中放置一个长的提交ID?

最终,我想做什么?在使用git reset --soft压缩提交后,我将把foo_ $ latest_commit合并到集成分支中。在后来的路上,我希望能够安全地删除第一个和第二个分支。如果第一个分支的提示与第二个分支的名称中的提交ID匹配,我可以安全地删除第一个分支。

git git-checkout
1个回答
2
投票

...有没有办法在第二个分支的某处存储元数据......

不直接,没有。

请记住,每个分支名称只是一个指向提交的(可移动)指针,具有特殊属性,如果使用git checkout来“分支”,git commit会自动移动指针。各种其他命令愿意以各种方式移动它:例如,git merge --ff-only将以快进方式移动当前分支名称,而git reset将任意移动它。

那么:你在哪里可以存储元数据?这有点棘手。

Git由两个主数据库组成:存储库本身是一个键值存储,其中哈希ID作为键,存储库对象(blob,树,提交和注释标记)作为值。与此同时,refs/heads/*中的引用分支名称,refs/tags/*中的标记名称,refs/stash中的存储区等等 - 是一个键值存储,对键有一些略微奇怪的约束(参见大多数的git check-ref-format),其值为哈希值标识。

由于您的目标是(我认为)将分支名称与两个不同的哈希ID相关联,因此一种明显的方法是在refs中创建自己的命名空间。假设我们选择refs/bases/。对于名称为B(例如全名refs/heads/B)的分支,您只需要创建一个refs/bases/B。您可以在refs/bases/B中存储的唯一内容是哈希ID,但这正是您要存储的内容,因此您已完成。

您是否希望存储多个简单的哈希ID或其他内容,例如,如果您想存储另一个名称,则需要某种数据对象。您的选择是四种对象类型中的任何一种,但其中两种受到强烈约束:树或提交必须正确格式化。其中一个是弱约束的:带注释的标记对象必须包含另一个对象的哈希ID - 带注释标记的目标 - 然后可以包含任意文本。最后一个,blob,不受约束,因为它可能包含任意文本。

要创建带注释的标记对象,请使用git mktag。有关所需的标记格式,请参阅其文档。

要创建blob,请使用git hash-object -w,可能使用--stdin;看它的文件。

两者都输出一个哈希ID,然后您可以将其设置为要存储在refs/bases/Brefs/xyz-meta/B下的哈希ID或您选择的任何名称空间。

One last note

对于大多数Git用法,工作方式不是存储基本分支名称,也不存储基本提交哈希ID。相反,使用set subtraction来请求可达提交,格式如下:

  • 所有提交都可以从名称T(提示)到达;但
  • 排除从名称S到达的所有提交(停止)。

这正是git rebase对你传递它的参数所做的事情,例如:当你运行git checkout feature; git rebase develop时,Git枚举从feature可以访问的所有提交,减去从develop可以到达的所有提交。这在Git中很常见,它有git rev-list语法:develop..feature表示feature ^develop,意思是“提交可以从feature到达,不包括可以从develop到达的提交”。

(你可以通过你的元数据技巧获得的是自动记住适当的名字 - 但事实证明,在实践中,大多数人似乎并不需要这个。对于你的特定用法,它可能是一件好事,虽然我把这部分放进去是因为我相信将来,其他人会找到你的问题和这个答案,并认为这是一个聪明的方法来记住每个派生分支的“基础分支”。它是什么,但那不是这样的一个聪明的事情。)

© www.soinside.com 2019 - 2024. All rights reserved.