0

我有一个提交后挂钩,可以编辑特定的源文件(具体来说,将提交哈希写入 c# 类中的字符串)。脚本是:

#!/bin/sh
hashStr=`git log --pretty=format:'%H' -n 1`
str="public static class GitHash { public static readonly string CommitHash = \"$hashStr\"; }"
echo $str > MyApp\\MyNamespace\\gitHash.cs

相同的脚本在我的 post-rebase、post merge 等钩子中。它工作正常并且在 git 中显示为已修改,直到我将 GitHash.cs 文件添加到 skip-worktree:

git update-index --skip-worktree MyApp/MyNamespace/GitHash.cs

现在该文件根本没有被修改,并且保持在我将它添加到 skip-worktree 时的状态。如果我从跳过工作树中删除它,钩子会再次起作用(文件被修改)。如果我正确理解了skip-worktree,那么当我想在本地修改文件时使用它是可以的,但不想意外提交它们并且不想在我执行git diff 时看到这些文件。但是,它似乎以某种方式阻止了钩子编辑此文件?

所以,如果我想让文件被钩子修改并且不显示在 git diff 上,我该怎么办?

4

2 回答 2

2

我意识到这与您设定的路径不同,但是:

如果它纯粹是一个生成的文件,为什么还要将文件存储在源代码管理中?如果您将其从提交中删除(并且可能在 to 中删除.gitignore)并使生成它成为构建过程的一部分而不是钩子,那么您应该得到您所描述的行为。

于 2020-03-17T18:44:28.537 回答
0

从技术上讲,该skip-worktree位作为稀疏结帐的助手存在。以你现在的方式使用它是对位的滥用。但是,另一位 ,assume-unchanged是慢速lstat系统调用的助手,虽然您可以以相同的方式使用它,但这也是一种技术滥用。因此,无论哪种方式,您都不太走运。

如果可能的话,通常最好不要这样做。例如,如果您的构建系统可以创建适当的信息——将其写入一个永远不会提交的文件——这通常是要走的路。(这就是Mark Adelsberger 所说的。)但是,您可以让您的 post-commit 挂钩写入文件,但同时设置这些位中的一个或两个,这就是您正在做的事情。这只是意味着该文件不会进入新的提交:相反,索引会挂在该文件的副本上。

要将更新的文件放入新的提交中,您必须在进行新的提交之前将该文件复制到 Git 的索引 中。但请记住,您所做的每个提交都有一个新的、唯一的哈希 ID。这意味着您必须在知道哈希 ID 之前存储它。

换句话说,您可以存储在已提交文件中的哈希 ID 绝不是您可以进行的包含该文件的提交的哈希 ID。你可以在那之前拿到那个。也许这就足够了:您可以在提交之前存储当前提交的哈希 ID,确保它匹配除 new-hash-ID 文件之外的所有内容:

bit=skip-worktree
# or assume-unchanged: either will work, though both are technically abuse

git commit                    # make sure we commit what we have
hash=$(git rev-parse HEAD)    # get the hash ID of the current commit
echo "built from stuff that mostly matches $hash" > file.ext
git update-index --no-$bit file.ext
git add file.ext
git update-index --$bit file.ext
git commit -m "update build info"

但是你绝对不能在文件中存储具有正确哈希 ID 的提交的哈希 ID,因为你无法预测它将是什么:在文件中存储未来的哈希 ID 会改变未来提交的哈希 ID . 1


1这里的一个可能的例外是,如果您设法在散列函数中找到一个固定点。

于 2020-03-17T22:40:42.840 回答