Hu3sky's blog

Git

Word count: 1,797 / Reading time: 7 min
2018/09/03 Share

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@vultr gittest]# git add README.txt
[root@vultr gittest]# git commit -m "this is a test"
[master (root-commit) 2451c88] this is a test
Committer: root <root@vultr.guest>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

git config --global user.name "Your Name"
git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

git commit --amend --reset-author

1 file changed, 1 insertion(+)
create mode 100644 README.txt

git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
git add可以一次添加多个文件
目录结构类似于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── HEAD   
├── config # 存放git的一些信息
├── description
├── hooks
├── index
├── info
│ └── exclude
├── objects # 存放对象文件
│ ├── 0c
│ │ └── 14454dd8d472ef27843ac8c86bdba161c27a03
│ ├── info
│ └── pack
└── refs
├── heads
└── tags

git status 查看

版本库、工作区、暂存区(stage)

在这里要区分三个概念词:版本库、工作区、暂存区(stage)
1
提交一个文件的时候是分为git add、git commit两步的
当git add的时候,是把文件临时放在临时区stage中
当git commit的时候,是把临时区stage的所有内容提交到当前分支
当然这两个在objects目录都会生成一个对象文件,来存储数据。
其中index的内容其中就包含了一些当前版本下的文件信息以及对应的objects目录下的对象文件
2*

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通常用来存储文件的内容.
3
你可以使用git show命令来查看一个blob对象里的内容

1
2
[root@vultr 15]# git show 155b5cc95e
GGGGGGGGIT TEST

Tree 对象

一个tree对象有一串(bunch)指向blob对象或是其它tree对象的指针,它一般用来表示内容之间的目录层次关系
4
git show命令还可以用来查看tree对象,但是git ls-tree能让你看到更多的细节。如果我们有一个tree对象的SHA1哈希值,我们可以像下面一样来查看它:

1
2
3
[root@vultr objects]# git ls-tree ac8b
100644 blob 155b5cc95e7a704d137ce66bb73371a814d45aa1 README.txt
040000 tree 98befd965b7dd6243fe6badb87d89c58e25ba790 test1

就如同你所见,一个tree对象包括一串(list)条目,每一个条目包括:mode、对象类型、SHA1值 和名字(这串条目是按名字排序的)。它用来表示一个目录树的内容。
一个tree对象可以指向(reference): 一个包含文件内容的blob对象, 也可以是其它包含某个子目录内容的其它tree对象. Tree对象、blob对象和其它所有的对象一样,都用其内容的SHA1哈希值来命名的;只有当两个tree对象的内容完全相同(包括其所指向所有子对象)时,它的名字才会一样,反之亦然。这样就能让Git仅仅通过比较两个相关的tree对象的名字是否相同,来快速的判断其内容是否不同。
注意:所有的文件的mode位都是644 或 755,这意味着Git只关心文件的可执行位

Commit对象

“commit对象”指向一个”tree对象”, 并且带有相关的描述信息
5

你可以用 --pretty=raw 参数来配合 git showgit log 去查看某个提交(commit):

1
2
3
4
5
6
7
8
[root@vultr objects]# git show -s --pretty=raw e2f98
commit e2f98ce855f1976277616930b2fbd2f6c39b684c
tree ac8b874be562e5c7baf9551a534f7faa9e53e13f
parent 2451c88001c43ca58bb620100d009ed7e437258c
author root <root@vultr.guest> 1535971020 +0800
committer root <root@vultr.guest> 1535971020 +0800

a test catalog

你可以看到, 一个提交(commit)由以下的部分组成:

  • 一个 tree 对象: tree对象的SHA1签名, 代表着目录在某一时间点的内容.

  • 父对象 (parent(s)): 提交(commit)的SHA1签名代表着当前提交前一步的项目历史. 上面的那个例子就只有一个父对象; 合并的提交(merge commits)可能会有不只一个父对象. 如果一个提交没有父对象, 那么我们就叫它“根提交”(root commit), 它就代表着项目最初的一个版本(revision). 每个项目必须有至少有一个“根提交”(root commit). 一个项目可能有多个”根提交“,虽然这并不常见(这不是好的作法).

  • 作者 : 做了此次修改的人的名字, 还有修改日期.

  • 提交者(committer): 实际创建提交(commit)的人的名字, 同时也带有提交日期. TA可能会和作者不是同一个人; 例如作者写一个补丁(patch)并把它用邮件发给提交者, 由他来创建提交(commit).

  • 注释 用来描述此次提交.

对象模型

如果我们一个小项目, 有如下的目录结构:

1
2
3
4
5
6
7
8
9
$>tree
.
|-- README
`-- lib
|-- inc
| `-- tricks.rb
`-- mylib.rb

2 directories, 3 files

如果我们把它提交(commit)到一个Git仓库中, 在Git中它们也许看起来就如下图:
6
每个目录都创建了 tree对象 (包括根目录), 每个文件都创建了一个对应的 blob对象 . 最后有一个 commit对象 来指向根tree对象(root of trees), 这样我们就可以追踪项目每一项提交内容.

标签对象

7

CATALOG
  1. 1. Git创建
    1. 1.1. 创建版本库
    2. 1.2. 把文件添加到版本库
  2. 2. 版本库、工作区、暂存区(stage)
  3. 3. git 对象模型
    1. 3.1. 对象
      1. 3.1.1. Blob对象
      2. 3.1.2. Tree 对象
      3. 3.1.3. Commit对象
  4. 4. 对象模型
    1. 4.0.1. 标签对象