在Git中,我如何将当前提交的哈希写入到同一次提交的文件中?
在Git中,如果你预先计算未来的提交哈希,将其写入文件是不可能的,因为一旦修改任何文件,提交哈希就会改变。然而,有三种解决方法:
1. 使用脚本来递增“提交ID”并将其包含在某个地方。这种方法不太方便。
2. 在将要存储哈希的文件中添加.gitignore。这种方法也不太方便。
3. 在pre-commit中,存储上一个提交的哈希。因为在99.99%的情况下,你不会修改/插入提交,所以这个方法是可行的。在最坏的情况下,你仍然可以识别源代码版本。
我正在编写一个hook脚本,会在“完成时”在这里发布,但是比《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
对转换为真正的提交哈希 🙂
我不知道这种方法能否区分合并提交。很快会进行检查。
在Git中,有一种方法可以将当前提交哈希写入到同一次提交中的文件中。这可以通过在gitattributes中使用filter属性来实现。你需要提供一个插入提交哈希的smudge命令和一个移除提交哈希的clean命令,这样插入哈希的文件就不会因为提交哈希的变化而改变。
因此,提交哈希从未存储在文件的blob中;它只是在你的工作副本中展开。实际上,将提交哈希插入到blob中将变成一个无限递归的任务。任何克隆这个树的人都需要自己设置属性。
这是一个不可能的任务,而不是递归任务。提交哈希依赖于树哈希,树哈希又依赖于文件哈希,文件哈希又依赖于文件内容。你必须获得自洽性。除非你能找到SHA-1哈希的某种广义的不动点。
那么,在Git中是否有一种技巧可以创建不修改结果哈希值的跟踪文件呢?也许有一种办法可以覆盖它的哈希值。这将是一个解决方案。
O Tync: 不可能。修改文件意味着修改哈希值(文件的哈希值)- 这是设计上的,也是哈希函数的定义。
这是一个相当好的解决方案,但请记住,这涉及到必须在每次克隆仓库时手动安装的钩子。
在Git中,如果想要将当前的提交哈希写入同一次提交的文件中,可以采取类似于下面的方法:在构建/安装/部署过程中生成一个未跟踪的文件,并将SHA1写入其中。这样做非常简单(git rev-parse HEAD > filename
或者 git describe [--tags] > filename
),并且可以避免出现与Git跟踪的文件不一致的情况。
代码可以在需要版本号的地方引用这个文件,或者构建过程可以将这个信息合并到最终产品中。事实上,这也是Git自身获取版本号的方式 - 构建过程从仓库中获取版本号,然后将其构建到可执行文件中。
有人可以详细解释一下如何一步一步做吗?或者至少给个方向?
做什么?我已经提到了如何将哈希放入文件中;其余的部分可能涉及到你的构建过程?如果你想询问那部分的话,或许可以提一个新的问题。
在我的情况下,我在Makefile中添加了一个规则,每次构建都会生成一个名为"gitversion.h"的文件。详见stackoverflow.com/a/38087913/338479
也许你可以使用一个"git-checkout"钩子来自动化这个过程。但问题是这些钩子必须手动安装。