git原理:提交原理

当运行git add  git commit的时候,git底层都做了什么?

这里涉及到的底层命令:
git hash-object 讲对象写入到git object中
git update-index  更新暂存区
git write-tree  创建树对象(相应的有 git read-tree这个例子里没用)
git commit-tree 提交树对象
git cat-file 查看git object对象
git update-ref 创建更新引用对象
git symbolic-ref 更新HEAD指针


初始化一个仓库
$ git init
Initialized empty Git repository in F:/code/test/.git/

给一个文件中写入内容
$ echo "test" >> test.txt

将这个文件写入object中
$ git hash-object -w test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory.
9daeafb9864cf43055ae93beb0afd6c7d144bfa4

更新暂存区
$ git update-index --add test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory.

写入树对象
$ git write-tree
2b297e643c551e76cfa1f93810c50811382f9117

写入提交对象
$ echo 'first commit' | git commit-tree 2b297e643c
53c9ca31caf6c071b3fe984f66eea8048ff6fe90



通过log查看该提交对象
$ git log 53c9ca3
commit 53c9ca31caf6c071b3fe984f66eea8048ff6fe90
Author: xiaol <413902946@qq.com>
Date: Mon Nov 13 00:04:30 2017 +0800

first commit

通过cat-file查看该提交对象
$ git cat-file -p 53c9ca3
tree 2b297e643c551e76cfa1f93810c50811382f9117
author xiaol <413902946@qq.com> 1510502670 +0800
committer xiaol <413902946@qq.com> 1510502670 +0800

first commit


通过cat-file查看提交对象中的树对象
$ git cat-file -p 2b297e643c
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt


通过cat-file查看树对象中的文件对象
$ git cat-file -p 9daeafb986
test
 

 

上面是通过底层命令完成一次提交的过程,在这个过程中,写入了objects,更新了暂存区,创建了提交对象,到这步也可以通过git log 53c9ca3来查看提交信息了,但是还少了一步,那就是写引用,引用的作用就是一个用户友好的名字,来代替那些SHA-1值,引用被存储在 .git/refs/文件夹中。
$ git update-ref refs/heads/master 53c9ca31caf6c071b3fe984f66eea8048ff6fe90

备注:
  1.本质上其实就是在refs/heads里创建了一个master文件,里面的值是53c9ca31caf6c071b3fe984f66eea8048ff6fe90
  2.其实创建分支就是git update-ref refs/heads/分支名  想要检出分支的SHA-1
  3.标签:
    附注标签:一个标签对象,标签对象指向提交对象,标签指向标签对象
      $ git tag -a v1.1 53c9ca31c -m "test tag"
      $ cat .git/refs/tags/v1.1
      95e1cec6f171640451266f4e709a73a6d9382bf5
      $ git cat-file -p 95e1cec
      object 53c9ca31caf6c071b3fe984f66eea8048ff6fe90
      type commit
      tag v1.1
      tagger xiaol <413902946@qq.com> 1510583034 +0800
      test tag
    轻量标签:一个固定的引用,引用指向一个提交对象   
      $ git update-ref refs/tags/v1.0 53c9ca31caf6c071b3fe984f66eea8048ff6fe90
      xiaol@xiaol-PC MINGW64 /f/code/test (master)
      $ git tag -l
      v1.0
  4.远程引用和分支的区别:
    远程引用是只读的
    虽然可以git checkout到远程引用,但并不会将 HEAD 引用指向该远程引用。
    永远不能通过 commit 命令来更新远程引用
    远程引用被当作服务器上各分支最后已知位置状态的书签来


然后这个引用就创建出来了,并且可以直接使用它来替代53c9c
$ git log master
commit 53c9ca31caf6c071b3fe984f66eea8048ff6fe90
Author: xiaol <413902946@qq.com>
Date: Mon Nov 13 00:04:30 2017 +0800

first commit


最后一个问题是当前分支,也就是HEAD指针,它存在于 .git/ 目录下,本质上存的是指向引用的字符串,可以用cat命令或者文本编辑器打开,但是这样并不安全,git同样提供了一个更加安全的命令:symbolic-ref  当执行git commit的时候,会创建一个提交对象,并用HEAD文件中记录引用的SHA-1值设置提交对象的父提交字段

$ git symbolic-ref HEAD
refs/heads/master

备注: 
  1.切换分支到test其实执行的就是git symbolic-ref HEAD refs/heads/test
  

      



原文地址:https://www.cnblogs.com/413xiaol/p/7823692.html