如何启用Git仓库的标识字符串?

36

如何在Git存储库中的文件上启用ident $Id$?

4个回答

43

摘要: 建议在产品中嵌入版本信息的最佳方式是使用构建系统;有关详细信息和备选方法,请参见下文。


在Git(以及我认为通常也适用于其他具有原子提交的VCS系统)中,没有像单个文件的版本之类的东西。

Git支持按需扩展$Id:$关键字,但:

  1. 它仅在请求时执行。您必须指定(可能使用全局模式)一个文件(或一组文件)具有设置了ident 属性(在树中的'.gitattributes'文件中,或者在本地存储库设置中的'.git/info/attributes'中)。
  2. 它扩展为文件内容的SHA-1(或更确切地说是$Id:<blob的sha-1>$)。选择这种方式的原因是Git不会触及未在分支切换或倒带期间更改的文件;如果'$Id:$'扩展到修订信息,它将需要更新每个受版本控制的文件,例如在切换分支时。

Git支持一个相当广泛的$Format:...$占位符集,用于扩展提交信息(例如,$ Format:%H$ 由提交哈希替换),但:

  1. 仅在运行git archive时才进行扩展,并在其输出文件中执行。
  2. 它只是按需请求执行,由export-subst属性控制。

建议使用构建系统(在构建阶段)嵌入版本信息;例如,查看GitMakefileGIT-VERSION-GEN脚本在Git Web界面上使用的Makefile中的git.git存储库。

但是,您可以(滥用)使用clean/smudge过滤器驱动程序(通过filter属性)来获得类似于CVS的关键字扩展,扩展检出时的关键字,并在输入内容到存储库时将其清理。


过滤驱动程序如果真的有任何作用就太好了。目前它似乎只能将文件名作为参数,这甚至比ident过滤器还要少,因为它只能获取BLOB SHA1作为参数。如果我们可以将$Format:...$传递给过滤驱动程序命令行,那么一切都会变得更好。而且应该从文本文件字符集开始... - Arioch 'The
不存在单个文件的版本,但任何时候都存在所有文件的状态。该状态由哈希表示。 - George Stocker
@GeorgeStocker:是的,所有文件的状态都可以通过项目顶部树对象的SHA-1哈希表示,但这与blob对象的SHA-1哈希(即文件内容)不同。 - Jakub Narębski
如果一个文件没有版本,那么你也无法检索一堆文件的版本! - user12411795

19
你可以在 .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

链接至gitattributes(5)手册页面


4
据我所知,这只为特定文件提供SHA,而不是整个代码库的$Id$。 - Aaron
%Format% 是怎么样的? - Asclepius
2
亲爱的读者,请注意在上面的命令行片段中,“rm test.txt”非常关键。对现有文件进行checkout操作不会向其添加提交哈希。 - Jonathan Ben-Avraham

2

Jakub Narębski他的回答中建议(十多年前):

但是,您可以(通过过滤器属性)滥用干净/模糊过滤器驱动程序来获取类似于CVS的关键字扩展,在签出时扩展关键字,并在输入内容到存储库时清理它们。

批评者是(由Arioch 'The评论中提出)

如果过滤器驱动程序实际上具有任何功能,则过滤器驱动程序将非常好。
截至目前,它似乎只以文件名作为参数:这甚至比ident过滤器更少,后者会获得BLOB SHA1作为参数

使用Git 2.27(2020年第二季度),Git内容过滤器不再无力!

Git 2.27 提供了更多信息(例如,树状物中 blob 出现的对象,除了已经给出的路径之外),以供 smudge/clean 转换过滤器使用。
查看 提交 0c0f8a7提交 4cf76f6提交 3f26785提交 dfc8cdc提交 13e7ed6提交 c397aac提交 ab90eca(2020年3月16日),以及提交 a860476(2020年3月10日)由brian m. carlson(“”)
(由Junio C Hamano -- gitster --提交4e4baee合并,2020年3月27日)

convert: permit passing additional metadata to filter processes

Signed-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。


2

Git的ident与其他版本控制系统中的$Id$不同。作为一个不太好的解决办法,可以使用RCS和git一起来管理:RCS用于单个文件修订,而git用于整个项目的检查点。正如我所说的,这是一个不太好的解决办法,但有时候对某些事情来说还是有点意义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接