use*_*470 6 git version-control
我想确保我的可执行文件是使用最新版本的代码构建的.
例如,我可以在编译时获取当前的git commit并将其烘焙到可执行文件中; 然后,当运行可执行文件时,它会将其与当前的git提交进行比较,如果它们不匹配,则会抱怨代码已被修改并且已过期.
但是,在对代码进行少量更改后,有时我会在不进行提交的情况下重新编译.然后此方法不起作用,因为它只考虑已提交的更改.
是否有任何方便的方法以编程方式获取当前提交的哈希PLUS工作目录的状态,使用git或其他方式?
此外,这种做法有名称吗?
可以在当前工作树中创建和存储大部分更改,包括所有暂存、未暂存和未跟踪的文件,同时尊重 .gitignore。粗略地说,一个人需要
#!/bin/sh
{ git diff-index --name-only HEAD
git ls-files -o --exclude-standard
} \
| while read path; do
test -f "$path" && printf "100644 blob %s\t$path\n" $(git hash-object -w "$path");
test -d "$path" && printf "160000 commit %s\t$path\n" $(cd "$path"; git rev-parse HEAD);
done | sed 's,/,\\,g' | git mktree --missing
Run Code Online (Sandbox Code Playgroud)
第一个 diff 列出了与 HEAD 不同的所有跟踪文件。
然后我们找到未跟踪的,但排除被忽略的。
然后,我们将这两个命令的输出通过管道传输到一个循环中,tnatgit mktree为所有文件构造输入。
它的输出会通过sed,因为git mktree不会递归地构造树,但这里的实际路径并不重要,因为我们只需要一个哈希码,没有任何实际内容被存储以供检索。
最后,我们将这个ls-tree- 格式的输出传递给mktree,它构造指定的树并将其存储在 Git 中,并将哈希值输出给我们。
通过一点额外的努力,人们还可以保留有关权限的信息,甚至可能保留文件删除的信息。毕竟,这就是您进行实际提交时 Git 所做的事情。
有人可能会说,当您确实想要存储更改以供将来参考,但又不想为每一个小更改进行不必要的提交而污染索引时,所有这些环都是有用的。因此,它对于微版本的内部测试可能很有用,您可以将本地哈希记录为代码的实际版本,而不仅仅是非描述性-dirty标志,以查看当您忘记标记时代码到底在哪里失败或为每个工作版本提交它。有些人可能认为这是一个坏习惯,相反,它应该迫使您为每个成功的构建做出承诺,无论多么小 - 很难反驳这一点,但话又说回来,这都是为了方便。
如果您只想确定是否有任何未提交的修改,那很简单;只需运行git diff --quiet HEAD并检查返回码是否非零。
如果您实际上需要更改的哈希值,以便具有相同起始提交和相同本地修改的两个用户将获得相同的哈希值,那就更棘手了。git diff HEAD我的第一个想法是将into的输出通过管道传输,并将其连接到提交哈希,但不同的 Git 版本和配置选项sha1sum的输出可能会有所不同。git diff
或者,您可以用来git add -u . && git write-tree获取当前工作树的真实 Git 树对象。但这是一种破坏性的操作;它会破坏索引中已有的任何部分暂存的更改。