Linus 发疯文学欣赏
Git 是 Linux 之父 Linus Torvalds 于2005年开发的用于帮助管理 Linux 内核开发的开源版本控制软件。
美好的一天从阅读 Linus 的发疯文学开始。
(1) Linus 教你学习 Git
(2) Linus 评价 CVS (Concurrent Version System)
(3) 独一无二的 Linus
调侃结束,开始看代码
一、切换分支,make 和阅读 README
执行如下命令( checkout 后面那一串是第一次commit计算出来的哈希值),切换到最初版本的 git 分支。
$ git clone https://github.com/git/git.git
$ git log --reverse
$ git checkout e83c5163316f89bfbde7d9ab23ca2e25604af290
来自地狱的管理器,emmm,好中二啊救命:)
1.1 成功 make all
毕竟 Linus 老爷子开发的时候是2005年,一些库函数、编译器配置可能已经过时了。
(1)修改 Makefile 中的 LIBS 配置如下
LIBS = -lz -lcrypto
(2)安装函数库
sudo apt install zlib1g-dev
sudo apt install libssl-dev
(3)修改 cache.h 文件
将 61~63 行的变量声明加上 extern 关键字,不然 make 时会出现 “multiple definition” 错误。
extern const char *sha1_file_directory;
extern struct cache_entry **active_cache;
extern unsigned int active_nr, active_alloc;
最后在 Makefile 所在文件夹下执行 make all 即可,生成如下七个可执行文件:
- cat-file
- commit-tree
- init-db
- read-tree
- show-diff
- update-cache
- write-tree
1.2 README
Linus 可以说是在到处发癫,即使在 README 中也如此,他首先解释了一下为啥取名 Git 。
GIT - the stupid content tracker
“git” can mean anything, depending on your mood. ("git"叫啥取决于你的心情)
- random three-letter combination that is pronounceable, and not actually used by any common UNIX command. The fact that it is a mispronounciation of “get” may or may not be relevant.(未被 UNIX 系统使用的命令名,也可能是对 get 的错误发音,目前一切正常)
- stupid. contemptible and despicable. simple. Take your pick from the dictionary of slang.
- “global information tracker”: you’re in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room. (心情不错时它是好的信息追踪器,天使在唱歌,阳光撒遍房间)
- “goddamn idiotic truckload of sh*t”: when it breaks.(它没用时,白痴般的粪车)
二、按照执行顺序,解读7个可执行文件
2.1 init-db(相当于 git init)
$ ./init-db
defaulting to private storage area
defaulting 是执行 init-db 的输出语句,表示默认在当前目录下创建文件夹 " .dircache/objects/ " 。在 Linux 中以“.”开头的文件为隐藏文件。
文件名的来源是在 cache.h 中定义的两个宏
#define DB_ENVIRONMENT "SHA1_FILE_DIRECTORY"
#define DEFAULT_DB_ENVIRONMENT ".dircache/objects"
对于第一个宏,Linus 的解释是,若希望多个分支共享一个数据库区域(DB area),即不同分支经 SHA1 计算后的哈希值保存在同一个目录中,可以配置这个宏。好处是节省了空间,坏处是让查找效率降低。默认做法还是在当前文件夹下新建 " .dircache/objects/ " 文件夹。
// C语言中创建文件夹也是 mkdir,sha1_dir 就是 ".dircache/objects/",0700 是权限信息
// 创建成功返回 0,失败返回 -1
if (mkdir(sha1_dir, 0700) < 0) {
if (errno != EEXIST) {
perror(sha1_dir);
exit(1);
}
}
在 " .dircache/objects/ " 文件夹下还有从 00~ff 共256个文件夹,每个分支的哈希值计算完后取前两位,对应到指定的文件夹中。
for (i = 0; i < 256; i++) {
sprintf(path+len, "/%02x", i); // x表示16进制,02表示结果为两位,不够的在前补0
if (mkdir(path, 0700) < 0) { ... }
}
创建成功后的效果
🔎 插曲:cache.h 和 read-cache.c
源码中的所有的 C 文件都 #include "cache.h ",read-cache.c 则实现 cache.h 中声明的函数,初始化声明的变量,因此放在一起说。