探秘
.git下的文件作用
HEAD 表示当前工作区所在的管理位置,里面是一个文件位置索引,指向具体的commit Hash,比如ref: refs/heads/main。直接编辑HEAD,跟git checkout操作相同
config 当前local作用域的git的config,跟git config --local相同
refs 包含heads和tags,各分支和tags的引用
heads里放的是各分支的最新head,也就是最新commit位置;
- 其每个文件的内容是一个hash值,指定的是objects/下的文件,其中hash的前两个字符作为文件夹索引:比如某个head内容为f20a9b7593b5ad3848a7adba3649581436d69025,指向objects/f2/0a9b7593b5ad3848a7adba3649581436d69025
tags是作者给各个commit位置打的标识,可以理解为“里程碑”
info (除了exclude的其他作用待补充)
- exclude 配置不进行追踪的文件
-
.gitignore
- 说明:显式地阻止提交文件。
- 优势:.gitignore 文件本身提交至远程仓库,全组共享忽略文件配置。
- 局限:如果项目已经存在远程仓库,即使被加入 .gitignore,仍然可以进行修改并提交。本地的修改会显示在 git status 结果中。(要不进行追踪到文件不能add到暂存区或者添加到commit中)
- 使用方法:需要自己在工作目录下构造.gitignore文件吧,并在里面添加内容,然后可将.gitignore推送到远程仓库。比较常规的不同开发语言环境对应的.gitignore范本可以在网上找到
-
.git/info/exclude
- 说明:显式地阻止提交文件。
- 优势:exclude 文件本身不会提交至远程仓库,因此适合放一些个人定制的 「gitignore」 项目。
- 局限:和 .gitignore 存在同样地局限。文件若已存在远程仓库,则本地修改仍可以提交至远程仓库。本地的修改会显示在 git status 结果中。
-
description 对本git仓库的描述
objects 各种commit等对象,已各内容哈希值作为索引
hooks 是git 提供的,在发生特定事件时,允许用户添加自定义代码(或操作)的方式脚本。所有的示例都是shell脚本,这些示例的文件名是以.sample结尾的,要想使用它们,需要删除这个后缀。
logs 存放git log要显示的内容
cat-file命令
git cat-file -t name 可以查看name的类型,commit\tag\tree\blob
git cat-file -p name 可以查看内容
Git对象彼此关系
一个commit对应一个树,不可能对应两棵树,也就是某个commit不可能有两个parent,不会是两个分离的树共同的子节点,但它可以有多个子节点。
一个tree是对应某个时间点的工作目录的快照,本身一个tree也是一个文件夹,blob是非文件夹的单独文件。
一个blob跟文件名没有关系,只关联具体的文件内容,文件内容相同的视为同一个文件,避免存储浪费。如果是有多个不同文件名的文件,但是内容完全相同的话,那这个几个文件名也会指向同一个blob
一个commit会存储当前的tree,会记录其parent tree,然后是本次commit的提交信息:author、committer、message
注意,一个commit里的tree和parent实际都是以当前工作目录作为树的起始点,所以下面这里是有两个tree的,工作根目录一个,doc一个。
分离头指针情况
git checkout commitID
会提示“You are in 'detached HEAD' state”,表示当前工作在一个没有分支的情况下。
分离头情况下可以继续开发,可以继续commit。但是注意,以后checkout到其他commit或者branch的时候,在这个detached HEAD上开发的内容在未来将因为没有挂钩的branch而作为垃圾被清理。不过在刚刚checkout到其他分支的时候,还是有时间去弥补的。
在detached HEAD下执行了新的commit后,commit也会正常生成对应的object,但是查看git branch的时候会发现当前在* (HEAD detached from b00be14),查看.git/HEAD发现是一个commitID而不是一个ref的路径,查看.git/refs/heads下也没有对应当前的head,说明没有branch对应当前状态。
git diff A B可以指定对两个commit做对比