我希望确保我的可执行文件使用最新版本的代码构建。
例如,我可以在编译时获取当前git提交并将其嵌入到可执行文件中;然后当运行可执行文件时,它会将其与当前git提交进行比较,如果不匹配,则会提示代码已被修改且过时。
然而,有时候我会在未提交更改的情况下重新编译代码。这种方法就不起作用了,因为它只考虑提交的更改。
是否有一种方便的方法,可以使用git或其他方式以编程方式获取当前提交的哈希值加上工作目录的状态?
此实践是否有名称?
我希望确保我的可执行文件使用最新版本的代码构建。
例如,我可以在编译时获取当前git提交并将其嵌入到可执行文件中;然后当运行可执行文件时,它会将其与当前git提交进行比较,如果不匹配,则会提示代码已被修改且过时。
然而,有时候我会在未提交更改的情况下重新编译代码。这种方法就不起作用了,因为它只考虑提交的更改。
是否有一种方便的方法,可以使用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
首先,第一个 diff 列出了所有与 HEAD 不同的已跟踪文件。
然后,我们找到未跟踪的文件,但排除了被忽略的文件。
接下来,我们将这两个命令的输出传递到一个循环中,该循环构建所有文件的 git mktree
输入。
由于 git mktree
不会递归构建树形结构,因此我们需要通过 sed
处理其输出。但是,实际路径并不重要,因为我们只想要哈希码,而没有存储任何实际内容以供检索。
最后,我们将这个 ls-tree
格式化的输出传递给 mktree
,它会构建指定的树形结构并将其存储在 Git 中,并将哈希码输出给我们。
如果再加一点额外的努力,还可以保留有关权限甚至文件删除的信息。毕竟,这就是当您进行实际提交时 Git 所做的事情。
有人可能会认为在想要将更改存储以供将来参考时,所有这些步骤都是有用的,但不想为每个小更改污染索引,因此可能在内部测试中使用 微 发布。在这种情况下,您可以将本地哈希记录为代码的实际版本,而不仅仅是非描述性的 -dirty
标志,以查看您的代码失败的确切位置,当您忘记为每个工作版本打标签或提交时。有人可能认为这是一个坏习惯,应该强制您对每个成功构建进行提交,无论多么小——这很难争辩,但这只是为了方便。
-w
选项,因为没有必要将永远不会提交的东西放入仓库中。 - jthillhash-object
的 -w
开关,因此我们无法像上面描述的那样使用 diff。它需要存在以启用此功能。 - dangit hash-object -w
。 - jthillt = $(mktemp); GIT_DIR = $ t git init
,然后为git hash-object
和git mktree
命令添加前缀GIT_DIR = $ t
。 - James Z.M. Gao如果你只想确定是否存在未提交的修改,那很容易;只需运行git diff --quiet HEAD
并检查返回代码是否非零。
如果你实际上需要一些更改的哈希值,以便两个具有相同初始提交和相同本地修改的用户将得到相同的哈希值,那就比较棘手了。我的第一个想法是将git diff HEAD
的输出导入sha1sum
,并将其连接到提交哈希值,但是git diff
的输出可能因为不同的Git版本和配置选项而有所不同。
或者,你可以使用git add -u . && git write-tree
来获取当前工作树的诚实可靠的Git树对象。但这是一种破坏性操作,它会覆盖已经在索引中部分暂存的更改。
git diff --quiet && <compile-command>
结合起来,这样如果 git diff
返回非零值,就不会进行编译。然而,如果只有未跟踪的文件,git diff --quiet
仍将返回0。但是,做一次 git status
然后再启动源代码的构建/编译真的有多难呢? - user456814