Git 相当于 subversion 的 $URL$ 关键字扩展

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2059326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 04:01:23  来源:igfitidea点击:

Git equivalent of subversion's $URL$ keyword expansion

gitkeyword

提问by Rudedog

I am considering migrating from subversion to git. One of the things we use subversion for our sysadmins to manage things like configuration files. To that end, we put $URL$into each file, which expands to the file's location in the subversion tree. This lets the admins look at a file on some arbitrary host and figure out where in the tree it came from.

我正在考虑从 subversion 迁移到 git。我们为系统管理员使用 subversion 来管理配置文件之类的内容之一。为此,我们将$URL$每个文件放入,并扩展到文件在 subversion 树中的位置。这让管理员可以查看某个任意主机上的文件,并找出它来自树中的哪个位置。

The closest analog I could find is gitattributes. There is the filter=directive, but it seems that git doesn't communicate to the filter what filename it's filtering, which would be necessary to turn $URL$into a path.

我能找到的最接近的模拟是 gitattributes。有filter=指令,但似乎 git 没有与过滤器通信它正在过滤的文件名,这对于$URL$转换为路径是必要的。

There is also the identdirective, which would turn $Id$into the blob hash. This might be usable if one could map that back into a pathname, but my git-fu isn't strong enough.

还有一个ident指令,它将变成$Id$blob 哈希。如果可以将其映射回路径名,这可能有用,但是我的 git-fu 不够强大。

Any suggestions?

有什么建议?

The workflow is as follows:

工作流程如下:

  1. Admin commits changes to the VCS repo
  2. Admin updates a central location that has checked out the repo
  3. Admin pulls the changes to the host using cfengine
  1. 管理员提交对 VCS 存储库的更改
  2. 管理员更新已检出回购的中心位置
  3. 管理员使用 cfengine 将更改拉取到主机

回答by VonC

As mentioned in "Does git have anything like svn propset svn:keywordsor pre-/post-commit hooks?", Git does not support keyword expansion.

正如“git 是否有类似svn propset svn:keywords或 pre-/post-commit 钩子?”中提到的那样, Git 不支持关键字扩展。

"Dealing with SVN keyword expansion with git-sv" provides a solution based on git config filter(which is not exactly what you want) and/or gitattributes.

用 git-sv 处理 SVN 关键字扩展”提供了一个基于git config filter(这不是你想要的)和/或gitattributes的解决方案。



The closest example if file information expansion I have found it still based on the smudge/clean approach, with this git Hash filter, but the clean part removes it from the file, and no path can be found.

最接近的示例 if 文件信息扩展我发现它仍然基于 smudge/clean 方法,使用这个 git Hash filter,但是 clean 部分将它从文件中删除,并且找不到路径。

This threadactually spells it out (as well as mentioning some git-fu commands which might contain what you are looking for, I have not tested them):

这个线程实际上说明了它(以及提到一些可能包含您正在寻找的内容的 git-fu 命令,我没有测试它们):

Anyway, smudge/clean does not give the immediate solution to the problem because of smaller technical shortcomings:

  • smudge filter is not passed a name of file being checked out, so it is not possible to exactly find the commit identifier.
    However, this is alleviated by the fact that 'smudge' is only being run for the changed files, so the last commit isthe needed one.

  • smudge filter is not passed a commit identifier. This is a bit more serious, as this information is nowhere to get from otherwise.
    I tried to use 'HEAD' value, but apparently it is not yet updated at the moment 'smudge' is being run, so the files end up with the date of the "previous" commit rather than the commit being checked out.
    "Previous" means the commit that was checked out before. The problem gets worse if different branch is checkout out, as the files get the timestamp of a previous branch.

AFAIR, lack of information in smudge filter was intentional, to discourage this particular use of smudge/clean mechanism. However, I think this can be reconsidered given the Peter's use case: "checkout-only" workspace for immediate publishing to webserver.
Alternatively, anyone interested in this use case could implement additional smudge arguments as a site-local patch.

And then, there are small annoyances, which seems to be inevitable: if you change 'clean' filter and check out earlier revision, it will be reported as having modifications (due to changed 'clean' definition).

无论如何,由于较小的技术缺陷,smudge/clean 并不能立即解决问题:

  • smudge 过滤器不会传递正在检出的文件的名称,因此不可能准确地找到提交标识符。
    但是,由于 'smudge' 仅针对已更改的文件运行这一事实,这一点得到了缓解,因此最后一次提交需要的。

  • 涂抹过滤器未传递提交标识符。这有点严重,因为否则无法获得此信息。
    我尝试使用 'HEAD' 值,但显然在运行 'smudge' 时它尚未更新,因此文件以“上一个”提交的日期结束,而不是被检出的提交。
    “上一个”表示之前签出的提交。如果签出不同的分支,问题会变得更糟,因为文件获得了前一个分支的时间戳。

AFAIR,涂抹过滤器中缺少信息是有意的,以阻止这种特殊使用涂抹/清洁机制。但是,我认为考虑到 Peter 的用例,可以重新考虑这一点:用于立即发布到网络服务器的“仅结帐”工作区。
或者,任何对此用例感兴趣的人都可以将额外的涂抹参数实现为站点本地补丁。

然后,还有一些小烦恼,这似乎是不可避免的:如果您更改 'clean' 过滤器并检查早期版本,它将报告为有修改(由于更改了 'clean' 定义)。

回答by jofel

Since there is nowadays the %foption, scripts like git-rcs-keywordscan do the task.

由于现在有这个%f选项,像git-rcs-keywords这样的脚本可以完成这项任务。

It is already mentioned in this answer.

这个答案中已经提到了。

gitattributes(5) manpage:

gitattributes(5) 联机帮助页

Sequence "%f" on the filter command line is replaced with
the name of the file the filter is working on. A filter 
might use this in keyword substitution. For example:

[filter "p4"]
    clean = git-p4-filter --clean %f
    smudge = git-p4-filter --smudge %f

回答by Jakob Borg

Coming at the problem from a completely different angle, how do the files in question end up on the end hosts? I guess today it is either checked out there directly, or copied somehow from an already checked out repository on another host?

从完全不同的角度来看问题,有问题的文件如何最终出现在终端主机上?我想今天它要么直接在那里签出,要么以某种方式从另一个主机上已经签出的存储库复制?

If so, could you modify your process so that files are checked out to a git repository, and a script does the $URL$or other keyword expansion aftercheckout. That way you can do whatever substitutions you like, and only be limited by what can be figured out by a script in a checked out repository.

如果是这样,您是否可以修改您的流程,以便将文件签出到 git 存储库,并且脚本签出执行该$URL$或其他关键字扩展。这样你就可以做任何你喜欢的替换,并且只受检出存储库中脚本可以计算出的内容的限制。

回答by qneill

We use a "canonical path" solution in our deployments (they are all internal, FWIW).

我们在部署中使用“规范路径”解决方案(它们都是内部的,FWIW)。

All software goes in e.g. /d/sw/xyz/a.cor D:\SW\xyz\a.c

所有软件都在例如/d/sw/xyz/acD:\SW\xyz\ac

All URLs to the deployed files reflect that e.g. http://host/d/sw/xyz/a.c.

部署文件的所有 URL 都反映了,例如http://host/d/sw/xyz/ac

URLs to the repository files start at "sw" e.g. git://githost/gitrepo/xyz/a.c

存储库文件的 URL 以“sw”开头,例如git://githost/gitrepo/xyz/ac

We encode these canonical paths in the configuration (should it ever need to change), and we have scripts/APIs that generate/reference the URLs on the fly for dynamic linking among components.

我们在配置中对这些规范路径进行编码(如果需要更改),并且我们有脚本/API 可以动态生成/引用 URL 以在组件之间进行动态链接。