Git中不同的标识字符串方法?

5
我正在准备将公司从CVS转换到Git,某些工程师希望我们仍然可以使用CVS关键字字符串,例如$ Id:$。我已经阅读了有关在.gitattributes中使用ident设置实现此功能的所有信息,并且我理解为什么这是不可取的,尽管对于较小的源树可能是可能的(我们的源代码非常庞大,因此我认为这是不可能的)。
我们的工程师并不特别关心文件中的SHA1哈希值。他们只想知道:
1. 最后修改日期 2. 提交者姓名 3. 可能是提交消息
当浏览代码时,在文件头中查看此信息非常方便,我无法反驳这一点。 我想知道的是: 有没有办法在 git commit 之前的瞬间为所有暂存的文件添加信息?换句话说,在要提交的文件的工作副本上运行perl命令--用所需的信息块替换$ Id:$
这不需要任何.gitattributes操作。Git只需要知道如何合并两个这样的信息块,理想情况下是选择后者。贴上信息只是新版本中的一个文件更改。
我查看了预提交钩子中的内容,但它似乎被设计为不同的目的--不是用于编辑文件,而仅用于检查它们。我对此正确吗?
没有人尝试过这种方法吗?对我来说,这似乎比每次git更改版本时尝试过滤所有源文件要简单得多,这就是.gitattributes的含义。
非常感谢任何建议/警告/指针。

哎呀!我是其中一个工程师,小伙子! - Roboprog
3个回答

3

关键字展开部分在git文档中有详细说明,可以帮助你实现干净的关键字展开。

以下是一个扩展所需内容的Ruby脚本(未经测试):

#! /usr/bin/env ruby
data = STDIN.read
last_info = `git log --pretty=format:"%ad %cn %s" -1`
puts data.gsub('$Last$', '$Last: ' + last_info.to_s + '$')

设置过滤器

$ git config filter.last_expander.smudge expand_last_info
$ git config filter.last_expander.clean 'perl -pe "s/\\\$Last[^\\\$]*\\\$/\\\$Last\\\$/"'

设置.gitattributes

echo '*.txt filter=last_expander' >> .gitattributes

注意:(就像vonbrand所说的那样)这将为您提供您想要的字段扩展功能,并在提交时删除这些字段。但是,它的效果是使您的工程师能够在其工作目录中读取已检出文件中的字段。这不就是他们想要的吗?而且这不会让实际版本化内容混乱不堪,也不会包含任何冗余的元数据。

我特别询问的是在签入时添加/更新字段,而在签出时不需要做任何事情。我不明白这有什么不好的。每次签入/签出都必须清理整个代码库中的所有文件,这对我们来说会非常慢。(这是我对Git属性处理的理解 - 我错了吗?) - Mykle Hansen
我认为我在谈论让“clean”过滤器填写或更新文件中的infostamp符号,而不使用任何“smudge”过滤器。这似乎可以工作,但没有人这样做...我就是不明白为什么不这样做。 - Mykle Hansen
更新这些字段的一个明显问题是,每次提交时更新它们意味着它们在文件的每个版本中都会不同。这意味着它们将出现在文件每个版本的差异中。这也意味着这些字段将为所有合并创建合并冲突。那么,为什么重要的是这些字段被提交?重要的不是工程师可以在检出的文件中,在他们的工作目录中看到这些字段吗?他们不能轻易地看到存储库中的内容。 - Klas Mellbourn

3
RCS(因此也包括CVS)在checkout时会扩展$Id:$等内容,这些内容不会保存在文件中。它们实际上不能被保存,因为有人可能会将版本 1.8.2-rc10 重命名为普通的 1.8.2。如果有人想知道file来自哪里,git log file可以很好地回答这个问题,并提供比RCS更详细的信息。而且这是一个本地命令,不需要访问CVS服务器(因此在任何安装了git的地方都可以使用,并且非常快速)。

1
我们关心的不是要将版本添加到文件中,而是只想知道最近的编辑日期和编辑者的姓名。在checkin时将这些信息添加到文件中是否有问题? - Mykle Hansen
你会得到我所说的(以及更多)... git与CVS不同,不要期望它能够工作相同。 - vonbrand
1
请解释一下“foo log file”(git | svn | cvs)如何告诉我有关从源代码控制工作空间复制并部署在测试或生产中的文件的任何信息?如果是 复制的,我不需要知道,而当 其他人 弄糟了时,你就非常需要知道。 - Roboprog

0

这是解决方法:

  1. 添加以下 pre-commit 钩子:

    #!/bin/sh
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 .filters/keywords --
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 git add -u -v --
    
  2. 添加以下 commit-msg 钩子:

    #!/bin/sh
    awk '!/^[[:space:]]*(#|$)/{exit f++}END{exit !f}' "$1" && exit
    # NOTREACHED unless commit was aborted
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 .filters/keywords -d --
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 git add -u -v --
    
  3. 下载 ".filters/fraubsd-keywords" 文件,但将文件重命名为 "keywords":

    https://raw.githubusercontent.com/freebsdfrau/FrauBSD/master/.filters/fraubsd-keywords

  4. 编辑 "keywords" 文件,在顶部的 CONFIGURATION 部分更改:

    • FrauBSD 更改为 Header
    • _FrauBSD 更改为 _Header

之后,每次执行git commit命令时,文本$Header$和/或$Header: ... $将被翻译成$Header: file YYYY-MM-DD HH:MM:SS GMTOFFSET committer $

注意:您可能需要修改“关键字”脚本的一小部分,以便它能够处理更多或更少类型的文件。在撰写本文时,它只能处理“ASCII文本”或“shell脚本”文件。


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