我试图在这里用Git钩子做一些花哨的东西,但我真的不知道该怎么做(或者是否有可能)。
我需要做的是:在每个提交中,我都想获取其哈希值,然后使用此哈希值更新提交中的文件。
有任何想法吗?
我试图在这里用Git钩子做一些花哨的东西,但我真的不知道该怎么做(或者是否有可能)。
我需要做的是:在每个提交中,我都想获取其哈希值,然后使用此哈希值更新提交中的文件。
有任何想法吗?
Answers:
我建议您执行与您的想法类似的操作:将SHA1放在未跟踪的文件中,该文件是在构建/安装/部署过程中生成的。这显然很容易做到(git rev-parse HEAD > filename
或者也许git describe [--tags] > filename
),并且避免做任何疯狂的事情,例如以与git跟踪的文件不同的文件结尾。
然后,您的代码可以在需要版本号时引用该文件,或者构建过程可以将信息合并到最终产品中。后者实际上是git本身如何获取其版本号的方法-构建过程将版本号从存储库中提取出来,然后将其构建到可执行文件中。
编写当前的提交哈希是不可能的:如果您要预先计算将来的提交哈希,则在修改任何文件后它将立即更改。
但是,有三种选择:
pre-commit
,存储先前的提交哈希:)在99.99%的情况下,您无需修改/插入提交,因此,它将起作用。在最坏的情况下,您仍然可以识别源版本。我正在研究一个钩子脚本,它将在“完成时”发布到此处,但是仍然比Duke Nukem Forever发行更早了:))
更新:代码.git/hooks/pre-commit
:
#!/usr/bin/env bash
set -e
#=== 'prev-commit' solution by o_O Tync
#commit_hash=$(git rev-parse --verify HEAD)
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date
commit_hash=$(echo "$commit" | head -1)
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300
branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation
# Write it
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py
现在,我们唯一需要的是一个将对转换prev_commit,branch
为实际提交哈希的工具:)
我不知道这种方法是否可以区分合并提交。会很快检查出来
有人将我指向ident的“ man gitattributes”部分,内容如下:
身份
为路径设置属性ident时,git用$ Id:替换blob对象中的$ Id $,后跟40个字符的十六进制blob对象名,并在结帐时后跟一个美元符号$。在工作树文件中,任何以$ Id:开头并以$结尾的字节序列在检入时都将替换为$ Id $。
如果您考虑一下,这也是CVS,Subversion等所做的。如果查看存储库,将会看到存储库中的文件始终包含例如$ Id $。它从不包含任何扩展。仅在结帐时才扩展文本。
ident
是文件本身的哈希值,而不是提交的草率。来自git-scm.com/book/en/…:“但是,该结果用途有限。如果您在CVS或Subversion中使用了关键字替换,则可以添加一个日期戳-SHA并没有那么大的帮助,因为它是相当随机的,您无法确定一个SHA是否比另一个SHA更旧或更新。” filter
需要工作,但可以将提交信息放入(或移出)文件。
这可以通过使用gitattributes中的filter
属性来实现。您需要提供一个插入提交ID的命令,以及一个删除提交ID的命令,以使插入的文件不会仅仅因为提交ID而改变。smudge
clean
因此,提交ID永远不会存储在文件的Blob中。它只是在您的工作副本中扩展了。(实际上,将提交ID插入到Blob中将成为无限递归的任务。)克隆此树的任何人都需要为自己设置属性。
在提交框之外思考!
将其弹出到文件挂钩/检出后
#!/bin/sh
git describe --all --long > config/git-commit-version.txt
您可以在任何使用该版本的地方使用该版本。
让我探讨一下为什么使用git内部函数这是一个具有挑战性的问题。您可以通过以下方式获取当前提交的sha1
#!/bin/bash
commit=$(git cat-file commit HEAD) #
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum))
echo ${sha1[0]}
本质上,您对所返回的消息运行sha1校验和git cat-file commit HEAD
。当您检查此消息时,有两件事立即跳出一个问题。一个是树sha1,第二个是提交时间。
现在,可以通过更改消息并猜测在特定时间进行提交或安排提交所花费的时间来轻松地处理提交时间。真正的问题是树sha1,您可以从那里得到它git ls-tree $(git write-tree) | git mktree
。本质上,您正在对来自ls-tree的消息进行sha1校验和,该消息是所有文件及其sha1校验和的列表。
因此,您的提交sha1校验和取决于您的树sha1校验和,它直接取决于文件sha1校验和,该文件完成循环并取决于提交sha1。因此,您对自己可用的技术有一个循环性的问题。
如果校验和的安全性较低,则可以通过蛮力将文件的校验和写入文件本身。但是,我不知道用sha1完成任何任务的工作。这并非不可能,但就我们目前的理解而言,这几乎是不可能的(但谁知道几年后这将是微不足道的)。但是,由于您必须将(blob)校验和的(tree)校验和的(commit)校验和写入文件中,因此,这甚至更加难以实现。