【问题标题】:A different approach to ident-style strings in Git?Git 中 ident 样式字符串的不同方法?
【发布时间】:2013-03-03 09:19:18
【问题描述】:

我正在计划我的公司从 CVS 过渡到 Git,并且某些工程师希望我们仍然可以使用 CVS 关键字字符串,例如 $Id: $。我已经阅读了所有关于使用 ident 设置 .gitattributes 实现这一点的内容,并且我理解为什么它是不可取的,尽管对于较小的源代码树可能是可行的。 (我们的资源很大,所以我认为这是不可能的。)

我们的工程师并不特别关心文件中的 SHA1 哈希值。他们只想知道:

  1. 最后修改日期
  2. 提交者的姓名
  3. 可能是提交消息

他们发现在浏览代码时在文件头中查看此信息非常方便,我对此无可争辩。

我想知道的是:

有没有办法在 git 提交之前对所有暂存文件进行信息标记?换句话说,要在提交的文件的工作副本上运行 perl 命令——将$Id: $ 替换为所需信息块?

这根本不需要任何.gitattributes 操作。 Git 只需要知道如何合并两个这样的信息块,最好选择后一个。加盖信息只是新创建版本中的一个文件更改。

我在 pre-commit 钩子中查看过这样做,但它似乎有不同的意图——不是为了编辑文件,只是为了检查它们。我说得对吗?

没有人尝试过这种方法吗?对我来说,这似乎比每次 git 更改版本时都尝试过滤所有源文件更简单,这听起来就像 .gitattributes 所做的那样。

非常感谢任何建议/警告/指针。

【问题讨论】:

  • 是的!我就是这样的工程师中的一员,女士!

标签: git cvs checkin ident


【解决方案1】:

RCS(以及 CVS)在 checkout 上扩展 $Id:$ 等,这些不在保存的文件中。他们不可能是真的,有人可能会过来将版本1.8.2-rc10重命名为普通1.8.2。如果有人想知道file 来自哪里,git log file 会很好地回答这个问题,更多 详细信息比 RCS 无法提供。它是一个本地命令,无需访问 CVS 服务器(因此在 git 所在的任何地方都可用,并且是即时的)。

【讨论】:

  • 同样,我们关心的不是添加到文件中的版本。我们只需要最近的编辑日期和编辑者的姓名。在签入时添加到文件中是一件坏事吗?
  • 你明白了(以及更多)我所说的...git 与 CVS 不同,别指望它以同样的方式工作。
  • 向我解释“foo 日志文件”(git | svn | cvs)如何告诉我有关从源代码控制工作区复制并部署在测试或生产中的文件的任何信息???如果是复制了,我不需要知道,那就是当别人搞砸了,然后你非常需要知道.
【解决方案2】:

git documentationKeyword Expansion 部分解释了如何进行干净的关键字扩展。

用于扩展您想要的内容的 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 所说)这为您提供的,以及您很可能想要的,是 checkout 时的字段扩展和提交时删除的字段。但效果是您的工程师将能够读取其工作目录中签出文件中的字段。这不是他们想要的吗?这不会用任何冗余元数据混淆实际版本化的内容。

【讨论】:

  • 我特别询问在签入时添加/更新字段,而在结帐时根本不需要做任何事情。我不明白这有什么不好。每次结帐/签入时必须涂抹/清理仓库中的每个文件对我们来说非常慢。 (这是我对 Git 属性处理的理解——我错了吗?)
  • 我想我说的是让“干净”过滤器填充或更新文件中的 infostamp 符号,而根本没有任何“涂抹”过滤器。似乎它会起作用,但没有人这样做......我只是不明白为什么不这样做。
  • 一件肯定不好的事情是,在每次提交时更新这些字段意味着它们对于文件的每个版本都会有所不同。这意味着它们会出现在文件的每个版本的每个差异中。这也意味着对于 all 合并,这些字段会产生合并冲突。为什么承诺这些领域很重要?工程师可以在他们的工作目录中查看签出文件中的字段不是重要的事情吗?他们无法轻易看到存储库中的内容。
【解决方案3】:

这就是你解决这个问题的方法:

  1. 添加以下预提交挂钩:

    #!/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. 编辑“关键字”,在顶部的 CONFIGURATION 部分进行更改:

    • FrauBSD 到标题
    • _FrauBSD 到 _Header

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

注意:您可能需要修改“关键字”脚本的一小部分才能对或多或少的文件类型进行操作。在撰写本文时,它仅对“ASCII 文本”或“shell 脚本”文件进行操作。

【讨论】:

    猜你喜欢
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 2022-07-19
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 2020-12-03
    相关资源
    最近更新 更多