Git中的一个特殊hash

最近了解了一点Git的内部原理,看到了一个特殊的hash,所以写了这一篇文章来分享自己的看法。

==============

既然你读这篇文章,那就意味着你应该比较熟悉Git的一系列操作,不过,在你使用 Git 的时候,你有没有遇到以下hash:

4b825dc642cb6eb9a060e54bf8d69288fbee4904

可能你会觉得git中的每个对象都有一个hash值,谁会注意hash的数值。确实,没有人会注意。

但是上面的这个hash确实是一个很特别的hash,接下来就来说明为什么这个hash是一个特殊的存在。

git中hash从哪里来?

每个 git 存储库,即使是空存储库也将包含这段hash。这可以通过 git show 验证:

    $ git show 4b825dc642cb6eb9a060e54bf8d69288fbee4904
    tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904

那么这个hash是从哪里来的呢?在这之前我们需要了解一点Git的知识:_Git 的核心部分是一个简单的键值对数据库(key-value data store)。 你可以向 Git 仓库中插入任意类型的内容,它会返回一个唯一的键,通过该键可以在任意时刻再次取回该内容。_

我们可以使用git hash-object命令来存储一个对象并获取该对象的键。

    $ echo 'test' | git hash-object -w --stdin
    9daeafb9864cf43055ae93beb0afd6c7d144bfa4

Git 内部存储的数据类似下面这样,其中每个对象都有其对应的hash值:

Git 数据模型 from ProGit.v2

ps:如果你仍然好奇,Pro Git 的 Git Internals 章节有更多详细介绍。

那么接下来说正题,这个特殊hash是如何产生的呢?它实际上是一棵空树的哈希值。可以通过为空字符串的/dev/null创建对象哈希来验证:

    $ git hash-object -t tree /dev/null
    4b825dc642cb6eb9a060e54bf8d69288fbee4904
    //或者
    $ echo -n '' | git hash-object -t tree --stdin
    4b825dc642cb6eb9a060e54bf8d69288fbee4904

空树hash的特殊用处

空树hash可以与git diff一起使用。例如,如果你想检查目录中的空白错误,您可以使用 --check 选项并将 HEAD 与空树进行比较:

    $ echo "test  " > readme.md
    $ git add . && git commit -m "init"
    [master 6d8e897] init
     1 file changed, 1 insertion(+), 3 deletions(-)
    $ git diff $(git hash-object -t tree /dev/null) HEAD --check -- readme.md
    readme.md:1: trailing whitespace.
    +test

在编写 git hooks 时,空树hash也非常有用。一个相当常见的用法是在使用类似于以下的代码在接受新提交之前验证它们:

    for changed_file in $(git diff --cached --name-only --diff-filter=ACM HEAD)
    do
      if ! validate_file "$changed_file"; then
        echo "Aborting commit"
        exit 1
      fi
    done

如果有以前的提交,这可以正常工作,但是如果没有提交,则 HEAD 引用将不存在。为了解决这个问题,可以在检查初始提交时使用空树hash:

    if git rev-parse --verify -q HEAD > /dev/null; then
      against=HEAD
    else
      # Initial commit: diff against an empty tree object
      against="$(git hash-object -t tree /dev/null)"
    fi
    
    for changed_file in $(git diff --cached --name-only --diff-filter=ACM "$against")
    do
      if ! validate_file "$changed_file"; then
        echo "Aborting commit"
        exit 1
      fi
    done

参考

https://git-scm.com/book/en

https://floatingoctothorpe.uk/2017/empty-trees-in-git.html


首发于个人博客:方寸之间


后沿技术
技术分享:Linux/C++/Open source
3 声望
0 粉丝
0 条评论
推荐阅读
如何在安装 Linux 后修复 Windows EFI 分区
最近在电脑上安装了最新的 Arch Linux,这次不同于之前,使用了 Gnome 的桌面环境,用起来还不错,所以就按照我之前的配置文件,光速配置了一下电脑。然而当我配置 Windows 双启动的时候,却找不到 Windows 的 EF...

一鳞半爪大大人阅读 367

git 常用命令 记录
有错误和改进的地方望留言,谢谢 : )顺便推荐一下,git入门教程Git 教程图解 GitPro Git 2(中文版)Git 使用Git 使用规范流程Git 工作流程Commit message 和 Change log 编写指南全局设置git config --system //...

Luff阅读 3.2k

git/pip/easy_install/apt代理/源设置
在公司内网环境中,访问公网往往需要经过公司的代理,对于浏览器、IDE等开发工具,都提供了设置代理的配置,而git、pip、easy_install等CLI工具,则需要通过命令或配置文件进行代理设置;对于Python、Ubuntu、Mav...

乘着风1阅读 5.6k

低代码开发重要工具:jvs-logic(逻辑引擎)2.1.6版本功能清单
逻辑引擎是一种能够处理逻辑表达式的程序,它能够根据用户输入的表达式计算出表达式的值。在实际应用中,逻辑引擎通常被用于处理规则引擎、决策系统、业务规则配置等领域,具有广泛的应用前景。前面几期我们了解...

软件部长2阅读 457

被吐槽 GitHub仓 库太大,直接 600M 瘦身到 6M,这下舒服了
忙里偷闲学习了点技术写了点demo代码,打算提交到我那 2000Star 的Github仓库上,居然发现有5个Issues,最近的一条日期已经是2022/8/1了,以前我还真没留意过这些,我这人懒得很,本地代码提交成功基本就不管了。

程序员小富2阅读 1.4k评论 1

书写友好的提交信息
其中开头部分表明了本次提交的类型(是添加功能还是修复错误等),范围则描述了修改的影响面,然后是一段简要的描述,更多详细的信息则可以在正文中进行描述。

Kisstar阅读 3k

Coding 官方推出网站服务状态页面啦!
第一部分是系统运行状态。如下图,提示所有系统的运行状态,如 Coding 网站访问状态, Git 服务,QC 服务和 Paas 服务等:第二部分是系统指标。System Metrics 两个图表示的分别是 Coding 官方网站的实时响应时间...

CODING阅读 2.8k

3 声望
0 粉丝
宣传栏