在Git中,我该如何将当前提交散列写入同一提交中的文件

我想用Git挂钩来做一些奇特的事情,但我真的不知道该怎么做(或者如果可能的话)。

我需要做的是:在每一个提交我想采取它的散列,然后用这个散列提交更新文件。

有任何想法吗?

我build议你做一些类似于你的想法:把SHA1放在一个未跟踪的文件中,作为构build/安装/部署过程的一部分生成。 这很容易做( git rev-parse HEAD > filename或者git describe [--tags] > filename ),它避免了做一些疯狂的事情,比如结束一个与git跟踪不同的文件。

然后,您的代码可以在需要版本号时引用此文件,或者构build过程可以将这些信息合并到最终产品中。 后者实际上是如何得到它的版本号 – 构build过程从版本库中获取版本号,然后将其构build到可执行文件中。

有人指出我身份的“人gitattributes”部分,它有这样的:

IDENT

当为path设置属性ident时,git用$ Id:replaceblob对象中的$ Id $,后面跟着40个字符的hexblob对象名称,后面跟着美元符号$。 任何以$ Id开头的字节序列,在worktree文件中以$结尾的字节序列将在检入时replace为$ Id $。

如果你仔细想想,这就是CVS,Subversion等等。 如果您查看存储库,则会看到存储库中的文件始终包含$ Id $。 它永远不会包含扩展。 只有在结帐时,文本才会被展开。

编写当前提交哈希是不可能的:如果你设法预先计算将来的提交哈希 – 只要你修改任何文件,它就会改变。

但是,有三个选项:

  1. 使用脚本来增加“提交ID”并将其包含在某处。 丑陋
  2. .gitignore你要存储散列的文件。 不是很方便
  3. pre-commit ,存储以前的提交哈希 :)你不修改/插入在99.99%的情况下提交,所以,这将工作。 在最糟糕的情况下,您仍然可以识别源版本。

我正在做一个钩子脚本,将它放在这里“完成时”,但仍然 – 早在公爵公爵永远释放:))

UPD.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对转换为真正的提交哈希的工具:)

我不知道这种方法是否可以说明合并犯。 将尽快检查出来

这可以通过在gitattributes中使用filter属性来实现 。 你需要提供一个插入提交ID的smudge命令和一个clean命令来删除它,这样插入的文件不会因为提交ID而改变。

因此,提交ID从不存储在文件的blob中; 它只是扩展在你的工作副本。 (实际上将提交ID插入到blob中将成为一个无限recursion的任务。)任何克隆这棵树的人都需要为自己设置属性。

我不认为你真的想这样做,因为当提交中的文件被改变时,提交的散列也被改变了。

让我来探讨为什么这是一个使用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 git ls-tree $(git write-tree) | git mktree 。 基本上,你正在对来自ls-tree的消息进行sha1校验,这是所有文件及其sha1校验和的列表。

因此,您的提交sha1校验和取决于您的树sha1校验和,这直接取决于文件sha1校验和,这完成了圆并取决于提交sha1。 因此,你有一个循环的问题与自己可用的技术。

由于不太安全的校验和 ,已经certificate可以通过蛮力将文件的校验和写入文件本身; 但是,我不知道有什么工作能够完成这个任务。 这不是不可能的,但根据我们目前的理解(但是谁知道可能在几年内这将是微不足道的)几乎是不可能的。 但是,由于必须将文件中的(blob)校验和的(树)校验和(提交)校验和写入,所以这更难以暴力破解。