这篇博客将会介绍一点GIT的基本概念,重点是文件状态以及对应的GIT工程的三种目录,尤其是暂存区(stage area)。有点枯燥,但应该对大家了解GIT有一定的帮助
一点GIT的概念
几乎所有的操作都在本地
用过集中式版本控制系统(CVCS)的同学都知道,断网意味着你基本没法正常工作。记得07-08年那会还在用IBM的Clearcase,如果你发现开发部门突然一阵骚动,并有人开始在走廊聊天的时候,那就是断网的时候!我觉得这是CVCS带给我们最大的好处:中场休息! 因为在CVCS中,每一个对文件的操作都必须跟服务器沟通,如果断网基本就没法干活。当然,你说我直接在Windows的文件系统修改文件行不行?应该是行的,但要是你rename了这个文件的话,一会未必能checkin成功。 但如果在断网的时候,你是没有办法看到一个文件的历史记录的,因为每个文件的历史记录都保存在服务器的。
而上的各种不爽在GIT这种分布式版本控制系统里面就不会存在的!在GIT里面,除了你要拿到别人的代码改动,或者你想把代码改动提交到服务器上 这两个动作之外,其它的动作基本都可以在断网的情况下 通行无阻!因为在本地已经有了一份完整的历史版本库 能满足你99%的工作需要!
三个状态三座屋
在GIT的世界里,每个文件的状态不是tracked就是untracked。 track指的是该文件已经在GIT的监控范围之内了,该文件的每一点改动GIT都能跟踪到;untrack指的是该文件不在GIT的监控范围之内,它的改动GIT是不会去跟踪的。
而每个tracked的文件将会处于如下四种状态的其中一种:unmodified,modified,staged, committed。
unmodified说的就是这个文件木有动过
modified是指你的文件已经改动了,但是还没有保存到你的本地数据库里面;
- staged是指你的文件改动了,并且添加到暂存区里面,下次提交就会把这些改动保存到本地数据库;
committed是指你的文件改动了,并且已经保存到本地数据库
每个真正进入版本库的文件都需要按照这种顺序执行:modified -> staged -> committed。同时这三种状态是互斥的,也就是说一个文件只能同时处于其中的一种状态而已!
上面的这三种状态也就引出了每个GIT工程的三个组成部分: git目录(Git Directory),工作目录(Working Directory),以及暂存区(stage area).
Git目录(Git Directory)
Git目录是GIT里面最重要的一部分,文件夹名字为”.git”。你从服务器clone一个项目的时候,其实就是clone一个”.git”的文件夹! Git目录里面包括了所有的元数据:当前分支,所有本地分支,remote信息,配置文件等等,另外最重要也是最大的就是 所有的GIT对象,这些GIT对象记录了所有的历史记录以及文件改动!Working Directory
从GIT角度看,一个工作目录就是GIT的一个版本,里面的文件是从压缩的GIT数据库里面解压出来,然后放在你的文件系统里。
从使用的角度看,我们开发时用到的所有文件都是 工作目录 里面的文件。
这些文件都放在 项目的根目录下,跟”.git”在同一文件层次目录暂存区(Stage Area)
暂存区保存着下一个commit将会包含的所有改动。但实际上,暂存区只是一个文件,而不是一个文件夹。暂存区的这个文件一般叫”index”,保存在”.git”目录下。
暂存区确实是GIT里面比较难懂的概念,可能也因为难懂,所以经常被遗忘!这里尝试着多说一点,但愿没有误导到大家。
首先我们看看如何将一个文件加到暂存区。当然我们要先对文件做修改
$ echo haha >>README.md
这时我们查看当前项目的状态:
$ git status
On branch D1.2
Your branch is up-to-date with 'origin/D1.2'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
从上面GIT详尽的说明中,我们已经看到了GIT跟踪到文件README.md已经处于modified的状态了。而且GIT也已经告诉我们该如何将文件加到暂存区了,我们接着来:
$ git add README.md
这时我们再看看当前项目的状态:
$ git status
On branch D1.2
Your branch is up-to-date with 'origin/D1.2'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README.md
GIT的信息里面说明了README.md的改动已经在暂存区里面了,下一个commit将会包含这个文件的改动。
其实当我们执行 git add 命令的时候,GIT做了两件事情:
1. 将本地文件的内容做个快照,并保存到GIT的对象库里面(.git/objects)
2. 将本地文件的时间戳,长度以及 第一步保存的对象ID保存到 暂存区(.git/index)里面去
我们可以来做一个比较大胆的比喻,能从某种程度上解释暂存区的作用。文件修改就好比是 商品,暂存区就好比是购物车。当我们修改好文件(选好商品)之后,通过 git add命令(拿起商品放到)放到暂存区 (购物车),然后通过commit(买单)将改动加到代码库(将商品拿回家里去)。当然,在这个过程当中,暂存区的文件是可以再回到工作区的(把商品放回货架上)
commit文件 | 购买商品 |
---|---|
修改文件README.md | 挑选商品 |
git add README.md | 把商品放到购物车 |
git reset HEAD README.md | 没想好,把一些商品放回去 |
git commit | 买单 |
下面这张《ProGit》书中的插图能很好地说明这三个目录之间的关系:
以上就是今天想跟大家分享的GIT基本概念,但愿没有误导大家,要是能有那么一点点帮助,那码几个钟头也就值得了!