使所有命令的 git 输出完整(非缩写)哈希

  • 本文关键字:缩写 哈希 输出 命令 git git
  • 更新时间 :
  • 英文 :


问题更新

(注我已经接受了罗兰的回答,因为它确实是正确的(和 最简单的)解决方案从 git 1.7.4.4 开始,但请考虑这个问题 关于早期版本的 Git 开放至 1.7.0.4。

这个问题有点漫无边际(主要是由于我的编辑 随后试图建立有关情况的更多信息),但 标题中的文本是最重要的位。

也就是说:我正在尝试建立最终的方法,以确保所有git 命令将在其输出中显示完整(非缩写)哈希。

由于我专注于向后兼容性,因此需要涵盖旧版本 的 git 1.7。理想情况下,这些解决方案适用于 git 1.7.0.4(用于 仍然支持的 Ubuntu 10.04 LTS),但我会对最少的 1.7.2.5 (适用于 Debian 6/挤压 LTS)。任何需要版本晚于以下版本 1.7.9.5(Ubuntu 12.04 LTS)绝对不理想,但我仍然很想听 关于他们。

请注意,我不希望失去缩写哈希的能力-- 这个问题背后的目的是确保工具与 Git 交互 始终可以访问完整且明确的哈希值。当我手动使用 git 时 命令行 我大部分时间都想要正常的缩写。

Roland Smith 关于使用 Command Line 参数覆盖的建议core.abbrev看起来很理想,但遗憾的是只能从 v1.7.4.4 开始工作(如core.abbrev以前不存在)。我怀疑这意味着我们确实需要确定 最全面的特定于命令的参数集(如git blame -l) 以产生等效的效果。

带有编辑的原始问题

一些(大多数?)git 命令默认输出缩写哈希。为 实例git blamegit-annotate都这样做,而这一事实正在跳闸 当冲突出现时,提升当前的 Emacs 支持(就像他们在 git 之前可以做的那样) 1.7.11.1 -- 请参阅下面的编辑 1),因为模棱两可的哈希值会导致错误,当 试图对它们采取行动)。


开始编辑 1

我在更新日志中注意到以下内容,这表明原始问题 这引发了这个问题的问题不会出现在最新版本的 吉特。

Fixes since v1.7.11.1
---------------------
* "git blame" did not try to make sure that the abbreviated commit
object names in its output are unique.

如果是这样,git 应该保证唯一性(至少在 命令运行时间)对于任何 git 命令报告的所有对象名称,然后 这将大大减轻我的担忧;但显然是解决 支持早期版本的 Git 的问题仍然是 利息。

结束编辑 1


这可以通过git blame -lgit annotate -l来解决,但我不知道 无论这两个命令是否是孤立的情况,我想确保 在其他情况下不会出现此问题。

我能看到的唯一相关配置是core.abbrev

设置对象名称缩写为的长度。如果未指定,则许多命令 缩写为 7 个十六进制数字,这对于缩写对象可能不够 名称在足够长的时间内保持唯一。

(但我不想删除查看缩写提交的选项),以及log.abbrevCommit其中:

如果为 true,则使 git-log(1)、git-show(1) 和 git-whatchanged(1) 假设--abbrev-commit.您可以使用--no-abbrev-commit覆盖此选项。

不过,--no-abbrev-commit论点并不是一件一致的事情——我认为 只有引用中提到的命令才能识别它(但请参阅编辑 2 下面)。


开始编辑 2

解析选项 API 文档指出:

布尔长选项可以通过前置no-否定(或取消设置),例如--no-abbrev而不是--abbrev.相反,以no-开头的选项 可以通过删除它来否定它。

因此,接受--abbrev命令(其中有很多)实际上将 都接受--no-abbrev?这个否定的选项通常不被提及; 当然,尽管--abbrev=40目前是等效的,即使没有 否定可用)。

我不清楚默认的布尔否定选项功能是什么时候 然而,介绍。

在我的版本 1.7.9.5 中,git-blame --no-abbrev结果为单字符对象 名字。事实上,它和--abbrev=0一样,因为责备使用n+1字符。 相反,我注意到git branch -v --abbrev=0给出了完整的 40 字符。

结束编辑 2


潜在问题命令的完整列表及其适当的选项 会很好,尽管理想的解决方案是 (或至少应该)被所有 git 命令(包括未来的命令)尊重,但在需要时保持显示缩写哈希的能力?

我想到的一个丑陋的方法是创建一个 git 配置文件, 导入原始配置文件(尽管我注意到导入只是 从 1.7.10 开始可用),然后将core.abbrev设置为 40;并通过以下方式使用它 调用 git 时的临时GIT_CONFIG环境变量,只要已满 提交是必要的。我想这会起作用,但我宁愿不这样做。

显然存在/曾经有错误,至少有些错误已经存在 固定;但是由于目标是支持尽可能多的(尽可能实用的)Git版本 用户可能合理地碰巧正在运行,我正在寻找的东西 向后兼容。

对于它的价值,这是我从手册中收集到的 版本 1.7.12.4:

接受--abbrev的命令(因此理论上也--no-abbrev):

  • 分支
  • 命令行界面
  • 描述
  • 差异
  • 差异指数
  • 差异树
  • .log
  • LS 文件
  • LS-树
  • 修订列表
  • 修订解析
  • 显示参考

其他选项:

  • git annotate -l
  • git blame -l
  • git diff --full-index
  • git log --no-缩写-commit
  • git show --no-缩写-commit
  • git whatchanged --no-缩写-commit

使用git -c core.abbrev=40 <command>应该适用于所有命令,因为它"将覆盖配置文件中定义的任何内容"。

它似乎是在8b1fa778676ae94f7a6d4113fa90947b548154dd年引入的(登陆版本 1.7.2)。

编辑2:正如phils所注意到的,core.abbrev参数是在1.7.4.4中添加的。

编辑:W.r.t.硬编码的哈希长度,在初始化程序/库时,您始终可以通过查看.git/objects/*中的文件名长度来查找哈希长度。

新更新的答案(2021 年)将适用于 Git 2.31(2021 年第 1 季度)

配置变量 'core.abbrev' 可以设置为 'no',以强制不使用缩写,而不管哈希算法如何。

当 Git 从 SHA1 切换到 SHA2 时,这一点很重要。

参见提交 a9ecaa0 (01 Sep 2020) 由 Eric Wong (ele828).
(由 Junio C Hamano 合并 --gitster-- 在提交 6dbbae1, 15 Jan 2021)

core.abbrev=no:禁用缩写

署名:黄志豪

这允许用户通过禁用缩写来编写与哈希无关的脚本和配置。

使用"-c core.abbrev=40"在SHA-256中是不够的,"-c core.abbrev=64"在今天的SHA-1存储库中不起作用。

[JC:调整的实现,添加了文档和测试]

git config现在在其手册页中包含:

如果设置为"no",则不进行缩写和对象名称 以全长显示。

注意:使用git -c core.abbrev=x rebase -i适用于编辑器(将显示缩写的提交 SHA1)

但是:它还在内部使用相同的缩写SHA1来开始变基本身。

这将不再需要(这意味着根本不需要git -c core.abbrev=40 rebase -i)。

请参阅来自Kirill A. Shutemov的提交edb72d5,用于Git 2.3.1+(2015年第1季度/第2季度):

rebase -i:在整个脚本内部使用完整的对象名称

在早期,向最终用户显示的缩写提交对象名称是用硬编码--abbrev=7生成的;提交5689503(rebase -i:尊重core.abbrev,2013-09-28,Git 1.8.5+)试图让它尊重用户指定的core.abbrev,但它错过了编辑器的最初调用。

如今,我们尝试在内部使用完整的 40 个十六进制对象名称,以避免变基开始运行后可能出现的歧义。
变基期间新创建的对象可能与insn 表中列出的现有提交共享相同的前缀。
这些对象名称在调用序列编辑器以将insn 表重新发送给最终用户之前被缩短,然后在编辑器返回时扩展回完整的对象名称。

但是代码在第一次准备insn表时仍然使用缩短的名称,从而向用户输出"7个十六进制或更多"。

从一开始就更改代码以使用完整的 40 个十六进制提交对象名称,以使事情更加统一。

注意:对于交互式变基,"insn sheet"是指令表。有关说明,请参阅提交 3322ad4。

请注意,在 Git 2.12(2017 年第 1 季度)中,您可以使用--no-abbrevgit diff --no-index添加到命令列表中:

参见 提交 43d1948 (06 Dec 2016) 杰克贝茨 (jablko)。
(由Junio C Hamano --gitster-- 合并于 提交 c89606f,2016 年 12 月 19 日)

diff: 处理no-index情况下的--no-abbrev

有两个不同的地方解析--no-abbrev选项,以及缩写 SHA-1 的两个不同地方。
我们通常用setup_revisions()解析--no-abbrev,但在无索引的情况下,"git diff"直接调用diff_opt_parse()diff_opt_parse()直到现在才处理--no-abbrev。(然而,它确实处理了--abbrev
我们通常用find_unique_abbrev()缩写SHA-1,但是提交4f03666("diff:在存储库外处理sha1缩写,2016-10-20)最近引入了一种特殊情况,当您在存储库外运行"git diff"。

setup_revisions()也调用diff_opt_parse(),但不是为--abbrev--no-abbrev调用,它自己处理。
setup_revisions()设置rev_info->abbrev,然后将其复制到diff_options->abbrev。它通过将缩写设置为零来处理--no-abbrev。(此更改不会触及这一点。

将缩写设置为零在存储库外特殊中被破坏 案例,直到现在才导致真正的零长度 SHA-1,而不是 取零表示不要缩写。
然而,触发此错误的唯一方法是运行"git diff --raw"而不使用--abbrev--no-abbrev选项,因为

  1. 没有--raw它不尊重缩写(这很奇怪,但一直都是这样),
  2. 我们默默地把--abbrev=0夹在MINIMUM_ABBREV上,和
  3. --no-abbrev直到现在才得到处理。

存储库外部案例是三个无索引案例之一。这 另外两个是当您正在比较的文件之一位于 您所在的存储库,以及--no-index选项。

最新更新