惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
T
Threat Research - Cisco Blogs
H
Hacker News: Front Page
N
News and Events Feed by Topic
Know Your Adversary
Know Your Adversary
Cisco Talos Blog
Cisco Talos Blog
SecWiki News
SecWiki News
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
K
Kaspersky official blog
Forbes - Security
Forbes - Security
Webroot Blog
Webroot Blog
Schneier on Security
Schneier on Security
P
Privacy & Cybersecurity Law Blog
H
Heimdal Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
V
Vulnerabilities – Threatpost
T
Tenable Blog
T
Tailwind CSS Blog
P
Privacy International News Feed
WordPress大学
WordPress大学
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
博客园 - Franky
Hacker News: Ask HN
Hacker News: Ask HN
Jina AI
Jina AI
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
雷峰网
雷峰网
Vercel News
Vercel News
A
About on SuperTechFans
爱范儿
爱范儿
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog
The Last Watchdog
The Last Watchdog
Engineering at Meta
Engineering at Meta
Spread Privacy
Spread Privacy
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 司徒正美
量子位
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recorded Future
Recorded Future
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Martin Fowler
Martin Fowler
Project Zero
Project Zero

方寸之間

修复 Arch Linux 的内核缺失问题 - 方寸之間 安装定制化 Vim - 方寸之間 树莓派配置旁路由过程记录 - 方寸之間 Cloudflare Tunnel 不完全上手指南 - 方寸之間 解除 New Bing 地区和浏览器限制的方法 - 方寸之間 FRP 上手教程 - 方寸之間 深入理解 Linux nohup 命令 - 方寸之間 C++智能指针是什么 - 方寸之間 PGP 工作原理详解 - 方寸之間 如何恢复 Windows EFI 分区 - 方寸之間 Scaleway IPV6 server 申请及使用攻略 - 方寸之間 Arch Linux 升级系统提示签名无效 - 方寸之間 Arch Linux 音响有杂音的解决办法 - 方寸之間 Arch Linux 如何切换内核 - 方寸之間 Django 项目时区更改错误的解决方案 - 方寸之間 超简单的 Arch Linux + Windows 双启动教程 - 方寸之間 使用 UFW 配置 Linux 防火墙 - 方寸之間 深入理解数据库事务 - 方寸之間 CRLF 和 LF 之间的区别与联系 - 方寸之間 DNS 的更新是如何工作的? - 方寸之間 浅析 Linux 的 cron 命令 - 方寸之間 如何快速查看 github 代码库中早期 commits - 方寸之間 黑科技:使用 GitHub 搭建自己的短链接服务 - 方寸之間 Build site with Franklin.jl - 方寸之間 iwd 的使用教程 - 方寸之間 超好用的 UML 工具推荐 - 方寸之間 ArchLinux 安装配置笔记 (Updated) - 方寸之間 如何将 Julia 添加到 Jupyter Notebook - 方寸之間 费曼技巧:最好的学习方式 - 方寸之間 How to Create Linux Desktop Entry - 方寸之間 Make a TODO robot with Github Actions - 方寸之間 C++继承 多态 虚函数 - 方寸之間 C++ inline 关键字详解 - 方寸之間 C++ Static 关键字详解 - 方寸之間 C++ type conversion notes - 方寸之間 Solution for _CRT_SECURE_NO_WARNINGS error - 方寸之間 IR Homework - 方寸之間 Customize Ubuntu themes, icons and Shell - 方寸之間 恢复右键菜单的新建命令 - 方寸之間 Hugo+Github 搭建个人博客 - 方寸之間
Git 中的一个特殊 hash - 方寸之間
Mercas · 2022-01-30 · via 方寸之間

最近了解了一点 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 值:

image

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