假设我想编写一个小助手,它允许以可以通过refs
传播到克隆的方式将一些元数据附加到存储库中。简单的例子(一个 git-notes 克隆原型,甚至没有将笔记附加到任何其他 git 对象):
hash=$(echo "Just a comment" | git hash-object -w --stdin)
git update-ref refs/comments/just $hash
即我用哈希hash
创建一个blob
并将其称为refs/comments/just
,这样git fsck --unreachable
就不会抱怨它,git gc
永远不会prune
对象。
但这当然是一个非常简单的例子,实际上我对更复杂的功能感兴趣。在那里,我的问题是,我可以"合法"做什么,我应该绝对避免什么?
例如,SE 上的几篇帖子是关于用户必须从重复的tree
条目中恢复的。因此,一个"不要"是"不要创建具有重复条目的tree
"。另一个例子是">请确保您的对象是可访问的,这样git prune
就不会删除它们"。还有什么?
是否可以创建自定义对象类型?对树中的 blob 使用"无效"文件模式?在哪里可以找到概述?还是我应该手动检查git-fsck
的来源以查看哪些构成错误(以及哪些是可以忽略的)?
自定义对象和引用的注意事项?
注意事项:
-
备份存储库:在对存储库的内部结构进行重大更改之前,请创建备份。我建议在使用
git bundle create /tmp/foo-all --all
之前。
使用 非重复命名空间:如果要引入自定义 ref,请尝试使用不同的命名空间(如示例中的
refs/comments/
),以避免与 Git 的常规 ref 名称发生任何冲突。确保对象可访问性:您的自定义对象应始终可从某些引用访问,以避免
git gc
或最近的git maintenance
意外修剪。
在单独的存储库中测试:在将自定义项应用于主存储库或生产存储库之前,请在单独的存储库或克隆存储库中进行测试,以确认假设并确保没有意外后果。
坚持对象类型:坚持使用四种主要对象类型(Blob、树、提交和标记),以实现最大的兼容性。如果尝试存储自定义数据,通常将其存储为 Blob,然后从标记或提交引用它是有意义的。
注意 事项:
避免重复的树条目:如您所指出的,树对象不应包含重复的条目。这可能会导致意外行为。
不要使用无效文件模式:虽然对树中的 blob 使用自定义文件模式可能很诱人,但这可能会导致问题。坚持使用此处详述的识别模式(
040000
用于子目录(树),100644
用于文件(blob),100755
用于可执行文件,120000
用于符号链接)。避免创建自定义对象类型:Git 识别四种主要对象类型(blob、树、提交和标记)。引入自定义对象类型可能会破坏 Git 的内部机制和工具,这些机制和工具只期望这四个。
不要修改现有对象:Git 的完整性依赖于对象的不可变性。创建对象后,不应更改该对象。如果需要更改,请创建一个新对象并相应地更新引用。
避免与 SHA-1不一致:SHA-1哈希是 Git 中对象识别和验证不可或缺的一部分。任何可能在对象内容与其哈希之间产生不一致的自定义操作都是一个很大的禁忌。
jthill在评论中问道:
"甚至不将笔记附加到任何其他 Git 对象的笔记"和只是一个普通的边带分支(有自己的根)之间有什么具体区别?
Git 注释是一种在不修改对象本身的情况下将任意元数据附加到对象的方法。通常,这意味着在提交中添加注释。注释存储在它们自己的 ref 中,通常在
refs/notes/
下,但它们通过引用该对象的哈希值"附加"到另一个对象(如提交)。边带分支只是一个常规分支,但可能用于与主分支不同的目的。它有自己的提交历史记录和树。它存储在
refs/heads/
下,就像任何其他分支一样。
因此,jthill的建议:创建一个"mynotes
"分支并使用git worktree
(我在这里介绍).
这将为此元数据创建一个单独的工作区,与您的主要工作完全隔离。