标记/标记 Git 中的一组文件

Labeling / Marking a group of files in Git

有没有办法在逻辑上用 Git 中的标签标记一组文件? 我了解标签和 Gitlab 标签的工作原理,但是...在这两种情况下,这些标记都应用于提交。

我们使用的应用程序 ETL 使用特定的目录树,在识别 3 个文件属于解决方案 X 和另外 2 个文件(在同一目录中)属于解决方案 Y 时,该目录树不太灵活。

标记/标记文件的子集而不是将它们放在特定功能的文件夹中或按照命名约定进行编码...将使它们更容易识别。
顺便说一句,这些文件是 XML(ETL 作业)或平面文件 (SQL/DDL)。

你会怎么做?

Git 没有自然的方法来完成这个,因为它实际上只关心它被指示监视的文件中的更改。

虽然是大杂烩,但解决这个问题的方法是使用提交标签来引用处于特定状态的项目。同样,Git 不关心单个文件,甚至不关心它们是否相关;建立这种关系是你的责任。

由于每次要应用标签时都将这些文件分组到一个提交中是不切实际的,因此您至少可以考虑给您留个便条,提醒您哪些文件属于哪个解决方案。

参见 git notes:这将是一个文本注释,由您管理,列出了给定解决方案要考虑的文件。
对于给定的提交,您可以附加多个注释。

这是一种解决方法,以考虑到 Git 本身基于提交无法标记文件这一事实。

您要分别跟踪它们吗?如果是这样,我想知道您是否可以使用两个不同的本地 git 存储库来实现此目的。查看 this 答案,了解如何在同一目录中管理两个不同的 git 存储库。

否则,如果您只需要一种在文件系统上标记文件的方法,git 将无济于事。如何包含两个文件 .sol1.sol2 列出相应解决方案中的文件,然后为您的 git 操作编写一个小脚本。例如,当您执行 git status -sol1 时,它会首先对整个目录执行 git status,然后按 .sol 中的文件过滤掉它,依此类推。编写这样的脚本应该不难,我认为它在其他场景中也可能有用。如果您需要帮助,请告诉我。

正如其他人所说,没有任何内置功能可以做到这一点。但是,我们可能会注意到 Git 在存储库本身中存储了四种对象:blob(文件)、树(代表充满文件的目录)、提交(通过 [= 形成有向无环图) 50=]parent 标识符,每个提交携带一个 tree 对象、一个作者、一个提交者、它的父集和任意日志消息),以及带注释的标签对象(没有强定义的关系,但每个标签都有一个目标对象,通常是一个提交)。

旁白:git notes 的工作原理

Git 的 notes 在内部表示为提交。每个提交都有一组 "files" 作为它的树,它们的名字只是碰巧——完全是偶然的:-) ...咳咳——完全一样1作为存储库中的一组提交。当 git log 去显示 ID 为 C 的提交时,它 "accidentally" 检查 refs/notes/commits 是否存在,如果存在,是否存在文件named C 存在于 refs/notes/commits 指向的提交中,如果存在,它将将该文件的内容附加到日志消息中。所以这就是注释附加到提交的方式:Git 的一个内置部分检查是否有特殊引用(refs/notes/commits)指向包含树的提交 "file" (和它最终确实是一个文件,因为它是一个普通的 Git blob 对象)应该附加到提交日志消息中。

当您修改笔记集时,Git 只需使用新树进行新提交。新的提交指向之前的 refs/notes/commits 提交作为它的父提交,这样旧的注释仍然存在并且可以(有一些困难)被视为过去的样子(这曾经很难;我相信它变得更容易了)。 Git 的自然打包文件压缩处理得很好,因此笔记占用的 space 只随着新笔记的添加而线性增长。


1为了提高效率,对 "name" 进行了一些修改,例如,笔记文件不是命名为 deadbeefcafebabec0ffeedecadefadedbedcede,它可能是名为 de/ad/beefcafe....


因此,解决方案很明显(咳咳)

您想表示排列在一个目录或一系列目录中的一组文件。也就是说,当然,一个 tree 和 Git 有树对象。因此,您应该创建一个树对象来保存这些状态之一。

你没有说你是否希望保留这棵树的多个历史版本。如果这样做,解决方案很明显:像 git notes 那样处理它们,使用新的提交对象来存储每个新树,链接提交以使过去的版本可检索。如果不是,则完全由您决定是否创建提交对象,因为单个标记对象可以直接指向树对象。 (一些非 Git 工具可能对提交或其他标签以外的任何标签有问题。不过,Git 本身的 Git 存储库中有一些这样的标签。 )

在任何情况下,您还需要一个顶级引用来指向指向最新树的提交或注释标记对象。

创建树很简单:只需填充一个索引文件——不是常规文件,而是一个备用文件,您将其名称写入环境变量 GIT_INDEX_FILE——使用您希望它们出现的文件名在你的树中,通过 git add-ing 文件(如果它们还不存在,这也会将必要的 blob 放入存储库),然后调用 git write-tree。这会将索引转换为所需的树对象(之后您可以并且可能应该丢弃导出的 GIT_INDEX_FILE 设置),像往常一样将新对象的 ID 打印到标准输出。编写一个提交 and/or 标记对象以指向这棵树只是调用 git commit-tree and/or git mktag 的问题(它将自己的新对象写入存储库,打印像以前一样将 ID 输出到标准输出)。最后,使用 git update-ref 创建或更新指向标记或提交对象的引用——您现在已经重新实现了 git notes,但形式更适合您自己的需要。

您可以随时将任何保存的树提取到您选择的任何工作树,只需 git checkout 使用另一个临时索引。