Pro-Git-Notes
第4章 Git 服务器
4.8 GitLab
4.8.1 安装
GitLab 是使用数据库的 Web 应用.
可以从 这个网站 下载镜像.
4.8.2 管理
GitLab 的管理界面使用过 Web 访问的.
在浏览器中输入安装有 GitLab 的服务器的主机名或者 IP 地址, 然后使用管理员身份登陆.
默认用户名是 admin@local.host
. 默认密码是 5iveL!fe
第10章 Git 内幕
.git
目录下的:
- description 文件仅限于 GitWeb 程序使用.
- config 文件包含配置
- info 目录包含一个全局性排除文件, 记录不希望放在
.gitignore
文件中的忽略模式. - hooks 目录包含客户端或服务器钩子脚本
剩下的重要文件或目录:
- object 目录,存储个人数据库的所有内容, 所有的对象都在这里
- refs 目录,存储指针, 指向数据的提交对象
- HEAD 文件,指向已检出的分支
- index 文件,Git 用来保存暂存区信息.
10.2 Git 对象
Git 的核心就是一个简单的 “键-值” 数据存储.
用到的一个命令:
1 |
|
hash-object
表明要生成一个 blob 对象,其返回一个哈希值,-w
参数表示保存这个对象,--stdin
表明从 stdin 获取输入.
SHA-1 的散列值是 40 个字符的校验和. 其由存储的内容加上头部信息计算得出.
相同的内容会得到相同的散列值. 而这个散列值只会保存一份. 其只和文件内容相关,和文件名无关. git 不会存储文件名.
显示内容的命令:
1 |
|
这里的 -p
参数可能为 print
, cat-file
后面必须加一个参数.
使用 -t
(type) 参数可以获取类型.
10.2.1 树对象
其解决了存储文件名的问题.
树对象相当于目录,blob 对象相当于文件内容.
同样用 cat-file
查看树对象内容. 如:
可以看到,其保存了文件名. 也就是说,只有 commit
之后才会保存文件名. add
只能保存文件内容.
底层命令将文件添加至暂存区:
1 |
|
这里的 “文件名” 可以取其他的,其会最终存入树对象中.
其会修改 .git/index
文件的内容,
将树对象加入暂存区使用 read-tree
命令:
1 |
|
--prefix
参数即这个树对象名, 自己取即可.
10.2.2 提交对象
创建提交对象需要使用 commit-tree
命令. 需指明一个树对象的哈希值和父提交对象 (如果有).
1 |
|
或:
1 |
|
提交对象的格式:
- 快照顶层树对象
- 作者信息 (user.name, user.email) 和时间戳
- 空行
- 提交消息
10.2.3 对象存储
Git 构造出以对象类型作为开头的头部信息:
- 对象类型
- 空格
- 内容的长度
- 空字节
Ruby 代码:
1 |
|
Git 将头部信息和原始内容拼接在一起,计算 SHA-1 校验和.
然后用校验和的前两位作为子目录名,剩余为文件名,将原始内容用 zlib 压缩并存储在这个文件中.
因此,校验和只是标记路径,和内容无关.
10.3 Git 引用
Git 中的 “引用” (reference 或 ref) 就是用文件来存储 SHA-1 值,然后将这个文件当作一个指针.
位于 .git/refs
下.
更新某个引用,使用 update-ref
命令:
1 |
|
执行 git branch
这样的命令,Git 会使用 update-ref
命令将当前分支中最后一次提交的 SHA-1 添加到你要创建的新引用中.
10.3.1 HEAD
HEAD 文件是一个到当前所在分支的符号引用.
执行 git commit
命令时,该命令会创建一个提交对象,并把该提交对象的父对象设置为 HEAD 文件中引用所指向的 SHA-1 值. (即当前分支)
可利用 git symbolic-ref HEAD
命令来读取 HEAD 的值.
1 |
|
设置:
1 |
|
10.3.2 标签对象
标签对象与提交对象类似,其包含:
- 标签创建者
- 一个日期
- 一条消息
- 一个指针
但标签对象通常指向的是提交对象,而不是树对象.
有两种类型的标签:
- 注释标签
- 轻量标签
创建一个轻量标签, 其不会创建标签对象:
1 |
|
.git/refs/tags/v1.0
文件中的内容是提交对象的哈希值.
创建一个注释标签,其会创建一个标签对象.
1 |
|
-a
参数指明要创建一个注释标签.
.git/refs/tags/v1.1
文件中的内容是标签对象的哈希值.
10.3.3 远程引用
添加远程仓库并向其推送,Git 会将最后一次推送到该远程仓库的每一分支的值保存在 refs/remotes
目录中.
远程引用与分支 (refs/heads 目录下的引用) 的主要不同在于前者是只读,可以对其使用 git checkout
,但是 Git 不会使 HEAD 指向它,因此也就无法使用 commit 命令更新远程引用.
10.4 包文件
查看对象的大小用 git cat-file -s 哈希值
.
一个文件提交后,修改部分内容再次提交,新的对象并不是只保存差异.
Git 在磁盘上保存对象所采用的格式叫做 “松散式” 对象格式,但有时为了节省磁盘空间和提高操作效率,Git 会将最个这种格式的对象打包塞进一个叫做 “包文件” 的二进制文件中。
可手动执行 git gc
命令要求 Git 打包这些对象.
上述命令会删除提交了的对象,并创建包文件和索引文件,
- 包文件中包含了从文件系统中删除的所有对象
- 索引文件包含了针对包文件内容的偏移 (毕竟几个文件的内容都放进了一个文件中,要知道那一部分是哪一个文件)
打包可以进一步压缩空间。此时 Git 会查找名称和大小相近的文件,只保存不同版本之间的差异. 第二个版本完整地保存了文件内容,而原始版本是以差异方式保存的 (毕竟大部分访问的都是文件的最新版本).
可以用:
1 |
|
查看打包的内容.
10.5 引用规格
若添加了一个远程仓库, 如:
1 |
|
该命令会在 .git/config
文件中添加内容, 包括:
- 远程仓库名称,如 origin
- URL
- 用于获取的引用规格
如:
1 |
|
fetch
的格式为:
- 可选的
+
, 指示 Git 更新引用 <src>:<dst>
,<src>
是远程端的引用样式,<dst>
是远程引用在本地要写入的位置
Git 获取服务器端 refs/heads/
下的所有引用,然后将其写入到本地的 refs/remotes/origin/
.
可指定多个引用规格,即拉取多个分支:
命令如下:
1 |
|
修改 .git/config
文件:
1 |
|
10.5.1 推送引用规格
命令如:
1 |
|
配置文件为:
1 |
|
10.5.2 删除引用
从远程服务器中删除引用:
1 |
|
10.6 传输协议
主要使用两个传输协议:
- “哑” (dumb) 协议
- “智能” (smart) 协议
10.6.1 哑协议
10.6.2 智能协议
10.7 维护与数据恢复
git gc
中的 gc
是 garbage collect (垃圾回收) 的缩写. 其:
- 收集所有的松散对象并将其放到包文件中
- 将多个包文件合并成一个大的包文件
- 删除没有与任何提交关联的成旧对象
可以修改 gc.autol
和 gc.autopacklimit
来配置.
10.7.2 数据恢复
在使用 git reset --hard 哈希值
重置到一个旧的分支后,无法得知最后一次提交的 SHA-1 值。可使用 git reflog
工具查看.
每次提交或修改分支,引用日志 (reflog) 都会更新。
git update-ref
命令也会更新日志.
使用 git log -g
命令会将引用日志 (reflog) 按照正常的日志格式输出.
引用日志的内容保存在 .git/logs
中,若引用日志被删除,使用:
1 |
|
其会检查数据的完整性,显示出所有没有被其他对象指向的对象.
10.7.3 移除对象
git clone
会下载项目的整个历史记录,包括每一个文件的每一个版本.
有人添加了一个大文件在提交历史中,就算在本次提交删除,该文件也一直存在到提交历史中.
想要彻底删除这个文件的方法,可能会破坏提交历史.
可以执行 count-objects
命令快速查看磁盘空间的使用情况:
1 |
|
查找大体积文件:
1 |
|
具体删除操作看书.
10.8 环境变量
10.8.1 全局行为
GIT_EXEC_PATH
决定了 Git 从哪里查找它的子程序 (如 git-commit, git-diff). 可以用:
1 |
|
来检查当前设置.
Git 通过 HOME
查找全局配置文件.
GIT-PAGER
用于控制在命令行上显示多页输出的程序,没有设置则使用 PAGER
Git 运行 GIT_EDITOR
作为编辑器,如果没有设置,则使用 EDITOR
还有 PREFIX
, GIT_CONFIG_NOSYSTEM
, 具体看书.