.git 目录

我认为对于这个目录的研究,可以对Git的工作有一个很全面的了解,所以我会在学习和使用的过程中不时对此文档进行补充。


.git 目录下有如下内容:
     branches  COMMIT_EDITMSG  config  description  HEAD  hooks  index  info  logs  objects  refs
.git 目录下有如下内容:
     branches  COMMIT_EDITMSG  config  description  HEAD  hooks  index  info  logs  objects  refs

对于以上文件和目录可简单描述为:
    hooks:这个目录存放一些shell脚本,可以设置特定的git命令后触发相应的脚本;在搭建gitweb系统或其他git托管系统会经常用到hook script
    info:包含仓库的一些信息
    logs:保存所有更新的引用记录
    objects:所有的Git对象都会存放在这个目录中,对象的SHA1哈希值的前两位是文件夹名称,后38位作为对象文件名
    refs:这个目录一般包括三个子文件夹,heads、remotes和tags,heads中的文件标识了项目中的各个分支指向的当前commit
    COMMIT_EDITMSG:保存最新的commit message,Git系统不会用到这个文件,只是给用户一个参考
    config:这个是GIt仓库的配置文件
    description:仓库的描述信息,主要给gitweb等git托管系统使用
    index:这个文件就是暂存区(stage),是一个二进制文件
    HEAD:这个文件包含了一个档期分支(branch)的引用,通过这个文件Git可以得到下一次commit的       parent
    ORIG_HEAD:HEAD指针的前一个状态




hooks :


发现hooks目录下是一些脚本的样例文件。至于何时,以何种方式执行需要的的脚本,需要根据需要,先不细说。


info :
  .git/info下有一个exclude,
在将某个目录添加到 Git 版本库、或提交某个git版本库的改动时,可能希望忽略掉一些文件或目录(如编译时生成的.o、.a文件等),可以修改.git/info/exclude文件来实现。
举例如下:

vi .git/info/exclude

# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
*.[oa]        #忽略以.o或.a结尾的文件或目录
*.pyc        
*.exe       #忽略以.exe结尾的文件或目录
.*              #忽略以.开头的文件或目录
*.rar
*.zip
*.gz
*.bz2
*.db
*.sqlite

.git/info/exclude 这里设置的则是你自己本地需要排除的文件。 不会影响到其他人。也不会提交到版本库中去。

 .gitignore与之不同的是,这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
那么对于这些文件该如何处理呢?
 1.删除Git数据库中对该文件的追踪 git rm --cached
 2.把对应的规则写入.gitignore,让忽略生效
 3.提交,推送

.gitignore 还有个有意思的小功能, 一个空的 .gitignore 文件 可以当作是一个 placeholder 。当你需要为项目创建一个空的 log 目录时, 这就变的很有用。 你可以创建一个 log 目录 在里面放置一个空的 .gitignore 文件。这样当你 clone 这个 repo 的时候 git 会自动的创建好一个空的 log 目录了。

说太多了,在学这个的时候看到一些相关的东西,就记录在这个上面了。。。


logs:

                                 

进入“.git/logs”文件夹,可以看到这个文件夹也有一个HEAD文件和refs目录,这些就是记录commit历史记录的地方。我们可以通过commit的哈希值,把repo退到一个指定的状态。


另外:refs下:logs/refs/heads/master
                      logs/refs/remotes/origin/master

具体说明待补充。。。
     
     现举一例子:
          添加一个文件,并提交它。发现此时refs/heads/master 指向了新提交的ID,refs/heads/master就像一个游标,有新的提交时就会指向新的提交。
                    

游标可上可下,Git提供了git reset命令,可以将游标指向任意一个存在的提交ID。


git reset --hard HEAD^ 命令让游标指向HEAD^,HEAD^是HEAD的一个父提交,所以ls,new_one.txt不见了,出现了我之前提交的一个文件new-commit.txt(之前把它删了,所以上一个ls没有显示)。



  Git提供了git reflog 命令,用show子命令可以显示此文件的内容。然后把master改为所需要的值。另外恢复master的操作也是记录在日志中的。
      对于git reset命令还是有必要去了解的,很常用,而且很危险。应当去了解一下他的各种参数,以及可能出现的危险。

objects:
前面提到所有的Git对象都会存放在“.git/objects”目录中,对象SHA1哈希值的前两位是文件夹名称,后38位作为对象文件名。下面是之前提到的master最新的commit对象的哈希值:
     26012d1a51e0be8780d35a9dfa2bcf36b152fedf


在Git系统中有两种对象存储的方式,松散对象存储和打包对象存储

松散对象(loose object)

松散对象存储就是前面提到的,每一个对象都被写入一个单独文件中,对象SHA1哈希值的前两位是文件夹名称,后38位作为对象文件名。

打包对象(packed object)

对应松散存储,把每个文件的每个版本都作为一个单独的对象,它的效率比较低,而且浪费空间。所以就有了通过打包文件(packfile)的存储方式。

Git使用打包文件(packfile)去节省空间。在这个格式中,Git只会保存第二个文件中改变的部分,然后用一个指针指向相似的那个文件。

一般Git系统会自动完成打包的工作,在已经发生过打包的Git仓库中,object/pack目录下回成对出现很多“pack-***.idx”和“pack-***.pak”文件。

HEAD:
     指向master的一个游标。
可见HEAD的内容是指向一个引用:refs/heads/master
再看.git/refs/heads/master的内容,1b1a288f2cbaf1951f1007eef59668c28780e863。
用git cat-file -t命令查看其类型,类型为commit,是分支中最新提交的提交ID


查看这个提交的内容。


INDEX:
执行git status(或git diff命令)扫描工作区改动的时候,现依据.git/index文件中记录的(用于跟踪工作区文件的)时间戳、长度等信息判断工作区文件是否改变,如果工作区文件的时间戳改变了,说明文件的内容可能被改变了,需要打开文件,读取文件内容,与更改的原始文件相比较,判断文件是否被更改。如果文件内容没有被改变,则将该文件新的时间戳记录到.git/index文件中。因为如果要判断文件是否更改,使用时间戳、文件长度比较比通过文件内容比较更快。所以Git这样的实现方式可以让工作区状态扫描更快速地执行。


文件.git/index实际上就是一个包含文件索引的目录树,像是一个虚拟的工作区。在这个虚拟工作区的目录树中,记录了文件名和文件的状态信息(时间戳和文件长度等)。文件的内容并没有存储在其中,而是保存在Git对象库.git/objects目录中,文件索引建立了文件和对象库中对象实体之间的对应。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值