暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【Git】第五章:Git提交历史查看以及原理

魏卯卯 2020-12-26
1410

接下来我们要详细深入的去探索一下Git的提交历史以及原理。

git  log命令

    git  log可以查看提交历史。

    git  log  --patch  -1

    --patch 可以显示每次提交之间的diff,

    -n 可以指定显示最近几个commit。

    这个是命令很有用,可以看最近两次commit之间的代码差异,进行code review是比较方便的。

  

    git  log  --stat

    可以显示每次commit的统计信息,包括修改了几个文件,有多少行插入,多少行删除。

  

    git log --oneline

    显示简短的hash,每个commit显示一行

   

    git  log  --oneline  --graph

    这是最有用的,可以看到整个commit树结构,包括如何合并的,就显示每个commit的SHA-1和提交说明,同时SHA-1显示短值。

--oneline:显示一行,不要显示多行那么多东西,一行里,就显示commit的标识符,SHA-1 hash值,40位的;提交备注;显示分支和HEAD指向哪个commit

--graph:显示图形化的commit历史,这个大家后面学习到分支那里就知道了,如果有分支的话,commit历史会形成一棵树的形状,这个时候用--graph可以看清楚这颗commit树长什么样子,很有用。

注意看一下,log中最近一次提交 HEAD -> master 是什么意思?

分支简单了解:后面章节着重讲解

    版本控制系统中都有一个概念,叫做分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。即同样的一份代码拷贝多次,每次拷贝的代码刚开始都是一样的,然后不同的人可以基于几个拷贝的项目去开发;然后开发完之后,再将拷贝的代码合并在一起,这就是分支的过程。

    git里面每次git init之后,默认初始就创建一个分支,叫做master分支。

    我们每次写代码,然后git commit提交,都会形成一次新的commit,然后默认就是在master分支对应的代码拷贝上,进行代码修改和提交的

    每次提交之后,master分支就会对应着最新的一次提交

    HEAD,指针,指向了我们当前所处的分支,因为当前我们默认就处于master分支上,所以HEAD指针就是指向master的。

图解git原理


上面的文字太抽象,我们来画图理解一下:

上图为文件1和文件2存放git中的过程状态:

文件1、文件2新建后add到暂存区,再提交到仓库。

文件1修改后add到暂存区,在提交到仓库。


我们来分析一下在仓库中文件1和文件2的变化过程:

文件1和文件2新建

1、在新建的文件1commit到仓库后,会在仓库中形成一个blob的数据结果,文件1和文件2的V1版本都以blob的形式存储到了仓库中。

2、同时还有一个tree object,它会存在两个指针分别指向两个blob。tree object其实就是一个指针,用于指向仓库的blob文件的。

3、commit  object就是对应的commit的信息。如:

4、master本地分支其实是一个指针,指向的是最新一次commit。

5、HEAD也是一个指针,他来区分当前是哪一个分支。

文件1修改

1、文件1修改后commit到仓库里面,此时又回新创建一下修改了的文件1的V2版本的blob。

2、创建一个新的tree来指向 文件1 V2 blob 和 文件2 V1 blob。

注意:

文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。

git会根据文件进行计算hash身份验证,如果hash相同则表示没有修改过。

3、会有一个新的commit object信息,指向的tree object是新创建的tree object;

也会有指向上一次commit的指针,指向hash:1234567的commit。object。

4、此时的master指针就指向了最新的一条commit object。

5、HEAD由于分支没变所以依然指向master本地分支。

commit object原理总结:

实际上每次我们执行一次commit,git都会存储一个commit object,这个commit object中会包含一个指针,指向这次提交文件的快照。这个commit object同时也包含作者的姓名和邮箱,提交说明,以及对上一次commit object的指针。

将一个文件版本放入暂存区的时候,就会计算一个校验和,然后提交的时候会将文件内容以blob的方式放入版本库中,同时在暂存区放入这个文件版本的校验和。接着git会创建一个commit object,其中会包含元数据,以及一个指针指向版本库中的文件快照。

也就是说,每次执行一次提交,都会在版本库中包含这么几个东西:一个blob,每个文件都会有一个blob来存储这个文件的本次提交的快照;一个tree,这个tree会包含对本次提交的所有文件的blob的指针;一个commit object,指向了tree的指针,作者,等信息。

接着如果再次执行一个提交,那么下一个提交同样会包含那些东西:每个文件一个blob,一个tree指向所有blob,一个commit object指向那个tree,同时这个commit object会有一个指针,指向上一个commit object。

最后多次提交,就会得到一颗完整的commit树。

git  reset命令

git  reset  --hard  HEAD^,就可以回退到上一个版本

HEAD^,代表的是commit(add methods for classes)的上一个commit(add two files)

git reset  --hard  HEAD^,就是将仓库、暂存区、工作区,全部恢复到上一个commit(add two files)对应的状态

git  reset  --hard HEAD^^,可以回退到上两个版本

git  reset  --hard HEAD~5,退回到HEAD之前的倒数第5个commit的状态

git  reset  --hard d324644,指定一个commit的hash值,回退到很老的版本

如果我们要回来怎么办?

git  reflog命令

上图应该很明确的说明了git log
git reflog
的区别啦。

git reflog
可以回到过去回到未来。

git log
只能回到过去。

知道了回到未来的版本号,就可以继续使用git reset
命令回到未来版本啦!


文章转载自魏卯卯,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论