Git 底层深入浅析 - 目录篇
前言
为什么要写这个呢?因为一直以来就想学习更多Git的相关知识,然后也因为某次演讲和公司大佬的分享,所以我想把我学习到的和理解的分享给大家。如果你也想一起学习Git,那就来和我一起学习吧!! Let's Go 😁
Note: 这个不太适合初学者,如果你想学习基础知识,请移步 Git 官网 以及你必须知道的Git命令
前置知识
- 三个关键词: 本地仓库
(local), 暂存区(index or stage), 远程(remote)
要了解Git底层工作机制,就要先了解它是什么?它有什么?我们先来了解一下.git目录都有什么吧。
.git目录
cd .git
ls -al

info: 目录包含一个全局性排除(global exclude)文件,用以放置那些不希望被记录在.gitignore文件中的忽略模式(ignored patterns)description: 文件仅供GitWeb程序使用,我们无需关心index:stage又称暂存区, 是一个索引config:存放各种设置文档, 包含项目特有的配置选项。
cat .git/config
包括默认remote, branch, 个人账户等信息
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:Rain120/study-notes.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "note-template"]
remote = origin
merge = refs/heads/note-template
可以通过一下命令来查看 or 配置你的 git信息
# 系统配置
git config --system --list
# 全局配置
git config --global --list
# 当前仓库
git config --local --list
# 打开编辑器来修改指定的配置文件; --system, --global or repository (默认)
git config -e / --edit
详见
git config --help
HEAD:指向当前所在分支(current branch)的指针文件路径(Hash),一般指向refs下的某文件


refs:存储指向各个分支的指针(SHA-1标识)文件, 包括分支和标签的引用
heads

remotes

tags


hooks:包含客户端或服务端的钩子脚本(hooks scripts)
Git Hooks 是定制化的脚本程序, 它能在特定事件发生之前或之后执行特定脚本代码功能。它分为客户端hooks (Client-Side Hooks) 和服务端hooks (Server-Side Hooks)。
Client-Side Hookspre-commit: 执行git commit命令时触发,常用于代码格式化prepare-commit-msg:commit message编辑器启动前default commit message创建后触发,常用于生成默认的标准化的提交说明commit-msg: 在git commit -m message后触发,常用于校验commit message是否标准post-commit: 整个git commit完成后触发,常用于邮件通知、提醒applypatch-msg: 执行git am命令时触发,常用于检查命令提取出来的提交信息是否符合特定格式pre-applypatch:git am提取出补丁并应用于当前分支后,准备提交前触发,常用于执行测试用例或检查缓冲区代码post-applypatch:git -am提交后触发,常用于通知、或补丁邮件回复(此钩子不能停止git am过程)pre-rebase: 执行git rebase命令时触发post-rewrite: 执行会替换commit的命令时触发,比如git rebase或git commit --amendpost-checkout: 执行git checkout命令成功后触发,可用于生成特定文档,处理大二进制文件等post-merge: 成功完成一次merge行为后触发pre-push: 执行git push命令时触发,可用于执行测试用例pre-auto-gc: 执行垃圾回收前触发
Server-Side Hookspre-receive: 当服务端收到一个push操作请求时触发,可用于检测push的内容update: 与pre-receive相似,但当一次push想更新多个分支时,pre-receive只执行一次,而此钩子会为每一分支都执行一次post-receive: 当整个push操作完成时触发,常用于服务侧同步、通知

.sample拓展名是为了防止它们默认被执行,安装一个钩子只需要去掉.sample拓展名即可。
相关使用,husky commitlint
参考
logs:存储日志的文件夹git log能够让我们清晰的知道我们or其他人具体每次提交都做了什么,以及精确定位到每一次代码修改。
# 最近 n 条日志
git log -n
git reflog
# log 提交时间、作者格式化
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
objects:存放git对象
Git 的底层存储从本质上讲是基于本地文件系统实现的 键值对型的数据库, key对应对象内容的 hash 值, value对应 git objects。
git objects分为 3类:
commit: 对象存储git中的提交信息.tree: 对象存储git仓库中的文件元数据信息, 包括文件名及目录结构信息等.blob: 对应的是git仓库中的文件内容.
我们将在下节更详细的讲述 git objects.