如何启用ident $Id$
Git 存储库中的文件?
4 回答
总结:在产品中嵌入版本信息的推荐方法是使用构建系统;有关详细信息和替代方法,请参见下文。
在 Git 中(我认为通常也在其他具有原子提交的 VCS 系统中)没有像version of a single file这样的东西。
$Id:$
Git 确实支持关键字的按需扩展,但是:
- 仅应要求完成。您必须指定(可能使用通配符模式)一个文件(或一组文件)具有一个
ident
属性集(在树中的 '.gitattributes' 文件中,或在本地存储库设置的 '.git/info/attributes' 中)。 - 它扩展为文件内容的 SHA-1(或更准确地说是
$Id:<sha-1 of blob>$
)。之所以这样选择,是因为 Git 不会去触碰分支切换或倒带时没有改变的文件;如果 '$Id:$' 扩展到修订信息,则需要更新每个版本控制的文件,例如在切换分支时。
Git 支持相当广泛的占位符集,$Format:...$
这些占位符扩展到提交信息(例如$Format:%H$
,被提交哈希替换)但是:
- 仅当在其输出文件中运行git archive时才会进行扩展。
- 它是根据请求完成的,通过
export-subst
属性控制。
嵌入版本信息的推荐方式是通过构建系统(在构建阶段)进行;例如,请参见 Git Web 界面中 Makefile 使用的 Git Makefile和GIT-VERSION-GEN脚本,用于 git.git 存储库。
但是,您可以(ab)使用 clean/smudge 过滤器驱动程序(通过filter
属性)来获得类似 CVS 的关键字扩展,在结帐时扩展关键字,并在将内容输入存储库时清理它们。
您可以通过ident
在文件中添加您想要此功能的文件的模式来执行此.gitattributes
操作。这将在签出文件时将 $Id$ 替换为 $Id:<40-digit SHA>$。请注意,它不会像在 CVS/SVN 中那样为您提供文件的修订号。
例子:
$ echo '*.txt ident' >> .gitattributes
$ echo '$Id$' > test.txt
$ git commit -a -m "test"
$ rm test.txt
$ git checkout -- test.txt
$ cat test.txt
Git 的 ident 不像 $Id$ 在其他版本控制系统中所做的那样。作为一个组合,将 RCS 与 git 一起使用:RCS 用于单个文件修订,而 git 用于检查整个项目。正如我所说,这是一个杂牌,但它确实有点道理(有时对于某些事情)。
Jakub Narębski在他的回答中建议(10 多年前):
但是,您可以(ab)使用 clean/smudge 过滤器驱动程序(通过过滤器属性)来获得类似 CVS 的关键字扩展,在结帐时扩展关键字,并在将内容输入存储库时清理它们。
批评是(由Arioch 'The在评论中)
如果过滤器驱动程序真的有任何力量,它会非常棒。
据了解,它似乎只将文件名作为参数:这甚至比ident
过滤器还要少,过滤器将 BLOB SHA1 作为参数。
使用 Git 2.27(2020 年第二季度),git 内容过滤器不再无能为力!
Git 2.27 为涂抹/清洁转换过滤器提供了更多信息(例如,除了已经给出的路径之外,正在转换的 blob 出现在其中的树形对象)。
请参阅提交 0c0f8a7、提交 4cf76f6、提交 3f26785、提交 dfc8cdc、提交 13e7ed6、提交 c397aac、提交 ab90eca(2020 年 3 月 16 日)和提交 a860476(2020 年 3 月 10 日),作者为brian m。卡尔森(``)。
(由Junio C Hamano 合并 -- gitster
--在4e4baee 提交中,2020 年 3 月 27 日)
convert
: 允许传递额外的元数据来过滤进程签字人:brian m. 卡尔森
在多种情况下,过滤器进程可以使用一些额外的元数据。
例如,有些人发现 ident 过滤器限制太多,并希望在他们弄脏的文件中包含提交或分支。
此信息在结帐期间不可用,因为此时 HEAD 尚未更新,并且它也不会在存档中可用。
让我们添加一种方法来将此元数据传递给过滤器。
我们传递我们正在操作的 blob、treeish(如果存在,则优先于树的提交)和我们正在操作的 ref。
请注意,我们不会在所有情况下都传递此信息,例如在重新规范化或执行差异时,因为在这些情况下它没有意义。
我们目前从过滤过程中获得的数据如下所示:
command=smudge pathname=git.c 0000
通过这一更改,我们将获得更像这样的数据:
command=smudge pathname=git.c refname=refs/tags/v2.25.1 treeish=c522f061d551c9bb8684a7c3859b2ece4499b56b blob=7be7ad34bd053884ec48923706e70c81719a8660 0000
关于这种方法,有几点需要注意。
对于 checkout 之类的操作,treeish 将始终是提交,因为我们无法检查单个树,但对于其他操作,例如存档,我们最终只能对特定树进行操作,因此我们将仅提供树作为 treeish .
类似的注释适用于 refname,因为在很多情况下我们不会有 ref。
和:
convert
: 为过滤器提供额外的元数据签字人:brian m. 卡尔森
现在我们已经连接了代码库以将任何额外的元数据传递给过滤器,让我们收集我们想要传递的额外元数据。
我们传递此元数据的两个主要地方是结账和档案。
在这两种情况下,读取 HEAD 不是一个有效的选项,因为直到写入工作树并且存档可以接受任意树之后,才会更新 HEAD 以进行检出。在其他情况下,HEAD 通常会反映当前使用的分支的 refname。
在其他情况下,我们传递的数据量较少,例如
git cat-file
,我们实际上只能从逻辑上了解 blob。