如何在Git存储库中的文件上启用ident $Id$
?
摘要: 建议在产品中嵌入版本信息的最佳方式是使用构建系统;有关详细信息和备选方法,请参见下文。
在Git(以及我认为通常也适用于其他具有原子提交的VCS系统)中,没有像单个文件的版本之类的东西。
Git支持按需扩展$Id:$
关键字,但:
ident
属性(在树中的'.gitattributes'文件中,或者在本地存储库设置中的'.git/info/attributes'中)。$Id:<blob的sha-1>$
)。选择这种方式的原因是Git不会触及未在分支切换或倒带期间更改的文件;如果'$Id:$'扩展到修订信息,它将需要更新每个受版本控制的文件,例如在切换分支时。Git支持一个相当广泛的$Format:...$
占位符集,用于扩展提交信息(例如,$ Format:%H$
由提交哈希替换),但:
export-subst
属性控制。建议使用构建系统(在构建阶段)嵌入版本信息;例如,查看GitMakefile和GIT-VERSION-GEN脚本在Git Web界面上使用的Makefile中的git.git存储库。
但是,您可以(滥用)使用clean/smudge过滤器驱动程序(通过filter
属性)来获得类似于CVS的关键字扩展,扩展检出时的关键字,并在输入内容到存储库时将其清理。
.gitattributes
文件中添加一个文件模式及其后跟的 ident
来实现此功能。这将在检出文件时将 $Id$ 替换为 $Id:<40位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
%Format%
是怎么样的? - AsclepiusJakub Narębski在他的回答中建议(十多年前):
但是,您可以(通过过滤器属性)滥用干净/模糊过滤器驱动程序来获取类似于CVS的关键字扩展,在签出时扩展关键字,并在输入内容到存储库时清理它们。
批评者是(由Arioch 'The在评论中提出)
如果过滤器驱动程序实际上具有任何功能,则过滤器驱动程序将非常好。
截至目前,它似乎只以文件名作为参数:这甚至比ident
过滤器更少,后者会获得BLOB SHA1作为参数。
使用Git 2.27(2020年第二季度),Git内容过滤器不再无力!
Git 2.27 提供了更多信息(例如,树状物中 blob 出现的对象,除了已经给出的路径之外),以供 smudge/clean 转换过滤器使用。gitster
--于提交4e4baee合并,2020年3月27日)
convert
: permit passing additional metadata to filter processesSigned-off-by: brian m. carlson
There are a variety of situations where a filter process can make use of some additional metadata.
For example, some people find the ident filter too limiting and would like to include the commit or the branch in their smudged files.
This information isn't available during checkout as HEAD hasn't been updated at that point, and it wouldn't be available in archives either.
Let's add a way to pass this metadata down to the filter.
We pass the blob we're operating on, the treeish (preferring the commit over the tree if one exists), and the ref we're operating on.
Note that we won't pass this information in all cases, such as when renormalizing or when we're performing diffs, since it doesn't make sense in those cases.
The data we currently get from the filter process looks like the following:
command=smudge pathname=git.c 0000
With this change, we'll get data more like this:
command=smudge pathname=git.c refname=refs/tags/v2.25.1 treeish=c522f061d551c9bb8684a7c3859b2ece4499b56b blob=7be7ad34bd053884ec48923706e70c81719a8660 0000
There are a couple things to note about this approach.
For operations like checkout, treeish will always be a commit, since we cannot check out individual trees, but for other operations, like archive, we can end up operating on only a particular tree, so we'll provide only a tree as the treeish.
Similar comments apply for refname, since there are a variety of cases in which we won't have a ref.
并且:
convert
:为过滤器提供附加元数据签名:brian m. carlson
既然我们已经将代码库连接起来,以传递任何附加的元数据到过滤器中,那么让我们收集一些我们想要传递的附加元数据。
我们传递此元数据的两个主要场合是检出和归档。
在这两种情况下,读取 HEAD 并不是一个有效的选项,因为在检出之前 HEAD 不会更新,直到工作树被写入,而归档可以接受任意树。在其他情况下,HEAD 通常反映当前使用的分支的 refname。
在其他情况下,我们传递较少量的数据,例如
git cat-file
,在这种情况下,我们实际上只能逻辑上了解 blob。
Git的ident与其他版本控制系统中的$Id$不同。作为一个不太好的解决办法,可以使用RCS和git一起来管理:RCS用于单个文件修订,而git用于整个项目的检查点。正如我所说的,这是一个不太好的解决办法,但有时候对某些事情来说还是有点意义的。
$Format:...$
传递给过滤驱动程序命令行,那么一切都会变得更好。而且应该从文本文件字符集开始... - Arioch 'The