Git创建
创建版本库
首先,选择一个合适的地方,创建一个空目录:1
2
3
4[root@vultr ~]# mkdir gittest
[root@vultr ~]# cd gittest
[root@vultr gittest]# git init
Initialized empty Git repository in /root/gittest/.git/
这样仓库就建立好了,可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -la
命令就可以看见
把文件添加到版本库
现在我们用vim
随便写一个README.txt
文件
一定要放到gittest目录下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件
接着,第一步,用命令git add
告诉Git,把文件添加到仓库
第二步,用命令git commit告诉Git,把文件提交到仓库:
1 | [root@vultr gittest]# git add README.txt |
git commit
命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。git add
可以一次添加多个文件
目录结构类似于
1 | ├── HEAD |
git status
查看
版本库、工作区、暂存区(stage)
在这里要区分三个概念词:版本库、工作区、暂存区(stage)
提交一个文件的时候是分为git add、git commit两步的
当git add的时候,是把文件临时放在临时区stage中
当git commit的时候,是把临时区stage的所有内容提交到当前分支
当然这两个在objects目录都会生成一个对象文件,来存储数据。
其中index的内容其中就包含了一些当前版本下的文件信息以及对应的objects目录下的对象文件
*
git 对象模型
所有用来表示项目历史信息的文件,是通过一个40个字符的(40-digit)“对象名”来索引的,对象名如
上图的一串hash 155b5cc95e7a704d137ce66bb73371a814d45aa1(SHA1哈希计算得来的)
这里15是目录而5b5cc95e7a704d137ce66bb73371a814d45aa1是文件名
但是所有git对象都是zlib压缩过的。
对象
每个对象(object) 包括三个部分:类型,大小和内容。大小就是指内容的大小,内容取决于对象的类型,有四种类型的对象:”blob”、”tree”、 “commit” 和”tag”。
- “blob”用来存储文件数据,通常是一个文件。
- “tree”有点像一个目录,它管理一些“tree”或是 “blob”(就像文件和子目录)
- 一个“commit”只指向一个”tree”,它用来标记项目某一个特定时间点的状态。它包括一些关于时间点的元数据,如时间戳、最近一次提交的作者、指向上次提交(commits)的指针等等。
- 一个“tag”是来标记某一个提交(commit) 的方法。
Blob对象
一个blob通常用来存储文件的内容.
你可以使用git show命令来查看一个blob对象里的内容
1 | [root@vultr 15]# git show 155b5cc95e |
Tree 对象
一个tree对象有一串(bunch)指向blob对象或是其它tree对象的指针,它一般用来表示内容之间的目录层次关系
git show命令还可以用来查看tree对象,但是git ls-tree
能让你看到更多的细节。如果我们有一个tree对象的SHA1哈希值,我们可以像下面一样来查看它:
1 | [root@vultr objects]# git ls-tree ac8b |
就如同你所见,一个tree对象包括一串(list)条目,每一个条目包括:mode、对象类型、SHA1值 和名字(这串条目是按名字排序的)。它用来表示一个目录树的内容。
一个tree对象可以指向(reference): 一个包含文件内容的blob对象, 也可以是其它包含某个子目录内容的其它tree对象. Tree对象、blob对象和其它所有的对象一样,都用其内容的SHA1哈希值来命名的;只有当两个tree对象的内容完全相同(包括其所指向所有子对象)时,它的名字才会一样,反之亦然。这样就能让Git仅仅通过比较两个相关的tree对象的名字是否相同,来快速的判断其内容是否不同。
注意:所有的文件的mode位都是644 或 755,这意味着Git只关心文件的可执行位
Commit对象
“commit对象”指向一个”tree对象”, 并且带有相关的描述信息
你可以用 --pretty=raw
参数来配合 git show
或 git log
去查看某个提交(commit):
1 | [root@vultr objects]# git show -s --pretty=raw e2f98 |
你可以看到, 一个提交(commit)由以下的部分组成:
一个 tree 对象: tree对象的SHA1签名, 代表着目录在某一时间点的内容.
父对象 (parent(s)): 提交(commit)的SHA1签名代表着当前提交前一步的项目历史. 上面的那个例子就只有一个父对象; 合并的提交(merge commits)可能会有不只一个父对象. 如果一个提交没有父对象, 那么我们就叫它“根提交”(root commit), 它就代表着项目最初的一个版本(revision). 每个项目必须有至少有一个“根提交”(root commit). 一个项目可能有多个”根提交“,虽然这并不常见(这不是好的作法).
作者 : 做了此次修改的人的名字, 还有修改日期.
提交者(committer): 实际创建提交(commit)的人的名字, 同时也带有提交日期. TA可能会和作者不是同一个人; 例如作者写一个补丁(patch)并把它用邮件发给提交者, 由他来创建提交(commit).
注释 用来描述此次提交.
对象模型
如果我们一个小项目, 有如下的目录结构:
1 | $>tree |
如果我们把它提交(commit)到一个Git仓库中, 在Git中它们也许看起来就如下图:
每个目录都创建了 tree对象 (包括根目录), 每个文件都创建了一个对应的 blob对象 . 最后有一个 commit对象 来指向根tree对象(root of trees), 这样我们就可以追踪项目每一项提交内容.