Git学习3:理解工作区和暂存区

时间:2022-03-09 04:07:58

在Git学习过程中,遇到了如下几个概念:工作区暂存区版本库。刚开始觉得Git不就是一个版本控制系统嘛,搞这么多概念干嘛。实际上正是这些概念,让Git的版本控制更加便捷和高效。而Git相比其他版本控制系统的一个不同是暂存区,实际上如果理解了暂存区,对Git的其他命令理解会很快。

工作区:简单理解就是需要进行版本的某个文件夹(假设为demo),这个文件夹有一些特殊之处——多了.git这个隐藏的文件夹

版本库:demo文件夹下的.git文件夹就是版本库

暂存区:暂存区可以理解为一个虚拟工作区,这个虚拟工作区会跟踪工作区的文件变化(增删改等操作)。这个工作区的位于.git文件夹下的index目录下

需要理解一点:当需要对工作区的修改提交到版本库前,暂存区会与工作区进行差异比较,如果工作区与暂存区的文件不一致,那么需要同步工作区的修改到暂存区,然后才可以提交到版本库。从这个意义讲,暂存区可以说是工作区和版本库的桥梁。好处自然是可以在真正提交到版本库之前做任意的操作,在需要真正提交的时候push到版本库。

Git之父Linus当初设计暂存区的初衷是由于每次在SVN中commit的时候都需要选择需要提交到版本库的文件,发现这个功能太鸡肋了。于是他想如果能够在真正commit做任意的修改,这些修改可以先放在暂存区中,如果后悔了不仅可以非常方便撤销,而且不会影响到现有的版本库。

下面通过一张图理解为工作区、暂存区和版本库的关系:

Git学习3:理解工作区和暂存区

从这张图可以得出以下信息:

  • Git的操作围绕工作区、暂存区(图中的index)、版本库(图中的master,实际上这是版本库的主分支)、对象库(图中的objects)几个部分进行
  • 工作区、暂存区和版本库都维持着一棵目录树
  • objects 标识的区域为 Git 的对象库,实际位于.git/objects目录下
  • 暂存区跟踪记录了工作区的文件名和文件状态(修改时间,文件大小等信息)
  • 图中的HEAD是一个指向最新commit的引用,可以通过版本回退的方式改变HEAD的指向
  • 执行git add会更新暂存区的目录树,同时将工作区的文件内容生成一个对象放入objects对象库中,在暂存区记录了该对象的索引index
  • 执行git commit会更新版本库的目录树,commit成功后版本库指向的目录树就是暂存区的目录树

在图中还有其他的命令,这里可以暂时不用理会,后面就会慢慢理解的。目前只需要理解git addgit commit这两个命令就可以。

既然暂存区会跟踪记录工作区的文件变化,那么Git是如何实现的呢?答案是时间戳。可以使用命令git status查看工作区与暂存区的差异情况,在执行git status时,首先会到.git/index下查看被跟踪的工作区文件的时间戳,如果发现自上次执行git add(执行git add可以让工作区的文件被跟踪)以来,文件的时间戳发生了变化,那么判断文件发生了改动,于是会与暂存区的原始文件与工作区中的该文件进行差异比较,如果发现两个文件内容不一致,那么就给出差异信息。