Git初始化
在我们探索Git的奥秘之前,除了需要安装Git环境以外,我们还需先配置Git的初始变量。
配置Git初始变量
配置用户名和邮箱(提交的时候需要):
$ git config --global user.name "USERNAME"
$ git config --global user.email "EMAIL@qq.com"
也可以设置命令的别名:
$ git config --global alias.st status
这样设置了之后,以后再用到 git status
时可用 git st
进行替代。
完成基本的初始化工作之后,我们就可以正式开始Git之旅了。
创建Git版本库及首次提交
$ cd /Users/jy/Desktop
$ git init demo
Initialized empty Git repository in /Users/jy/Desktop/demo/.git/
进入到我们制定的目录, git init demo
会为我们创建一个demo目录,并为其初始化Git版本库。
$ ls -a
. .. .git
可见,初始化版本库之后目录下会有一个.git的隐藏目录,这个文件就是整个版本控制实现的关键。
然后我们在目录中创建一个新文件:
$ echo "hello git" > hello.txt
然后我们进行第一次提交:
$ git add hello.txt
$ git commit -m "first commit"
[master (root-commit) 505f1bc] first commit
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
从输出可以看出,(root-commit)表示master分支的首次提交,提交的commit ID 为 505f1bc;
在Git工作区的某子目录执行git操作时,会从工作区的目录依次递归向上地查找.git目录,在非Git工作区执行git命令时,会提醒fatal: Not a git repository (or any of the parent directories): .git
Git 暂存区
理解Git暂存区
在执行 git status
或 git diff
命令时,会扫描工作区改动,先根据.git/index 文件中的时间戳、长度等信息判断文件是否有改动,若有改变则读取index中内容进行对比;若没有改动,则更新时间戳。
.git/index实际上是一个包含文件索引的目录树,记录了文件名和状态信息(时间戳和文件长度等)。而文件内容并没有存在这儿,内容保存在Git对象库.git/objects目录中,文件索引建立了文件和对象库中对象实体之间的对应关系。
git diff 命令
查看HEAD(版本库中当前提交)指向的目录树:
$ git ls-tree -l HEAD
100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f 10 hello.txt
// 1. -l: 显示文件大小 当前文件大小为10B
// 2. 100644: 文件属性 (rw-r--r--)
// 3. blob: blob对象(文件)
// 4. 8d0e41...: 40位的SHA1哈希值格式的ID
我们先新建个文件夹以及文件,再将其添加到暂存区中。
$ mkdir -p file/test
$ echo "my second file" >> file/test/second.txt
$ git add .
如果要查看暂存区的目录树:
$ git ls-files -s
100644 75d6370ae31008f683cf18ed086098d05bf0e4dc 0 file/test/second.txt
100644 8d0e41234f24b6da002d962a26c2495ea16a425f 0 hello.txt
如果想针对暂存区目录树使用 git ls-tree
命令,需要先将暂存区的目录树写入Git对象库(使用 git write-tree
)。
$ git write-tree
667f37c2876a1aac5b56a2617dc6312bf36a60a2
$ git ls-tree 667f37
040000 tree 645cf3cf0dedc40f52cb66dc152653e4adb143df file
100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f hello.txt
git diff 带不同参数的区别:
(1) 工作区和暂存区的比较:
$ git diff
diff --git a/hello.txt b/hello.txt
index 8d0e412..a497e7c 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
hello git
+second.
(2) 暂存区与HEAD比较:
diff --git a/file/test/second.txt b/file/test/second.txt
new file mode 100644
index 0000000..75d6370
--- /dev/null
+++ b/file/test/second.txt
@@ -0,0 +1 @@
+my second file
(3) 工作区与HEAD比较:
diff --git a/file/test/second.txt b/file/test/second.txt
new file mode 100644
index 0000000..75d6370
--- /dev/null
+++ b/file/test/second.txt
@@ -0,0 +1 @@
+my second file
diff --git a/hello.txt b/hello.txt
index 8d0e412..a497e7c 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
hello git
+second.
Git 对象
探索Git对象
通过 git log
命令,查看日志信息:
$ git log -l --pretty=raw
commit 3f3c6f4f91e29e08c72874f1dc5309eefd998b66
Author: JYGod <jiangyu@teddymobile.cn>
Date: Thu May 31 16:28:46 2018 +0800
second commit
commit 505f1bcf709e4cc1d4f5c7d150718444fba652e6
Author: JYGod <jiangyu@teddymobile.cn>
Date: Tue May 22 14:09:09 2018 +0800
first commit
我们可以看到之前的两次提交的相关信息。然后我们可以通过 git cat-file
命令来查看相应ID对应的Git对象的相关信息。
$ git cat-file -t 3f3c6f4f
commit
$ git cat-file -p 3f3c6f4f
tree 6bffd1c96739426e0025993332c7b0cc63d94e00
parent 505f1bcf709e4cc1d4f5c7d150718444fba652e6
author JYGod <jiangyu@teddymobile.cn> 1527755326 +0800
committer JYGod <jiangyu@teddymobile.cn> 1527755326 +0800
second commit
通过提交的ID进行对象查看,我们可以知道该对象属于commit对象,而该commit对象中记录了一个tree和parent。
$ git cat-file -t 6bffd1c
tree
$ git cat-file -t 505f1bcf
commit
这两个分别是tree对象和commit对象,也就是说,当前commit对象记录了本次提交所对应的目录树以及上一次提交的commit对象信息。我们再来看看那个tree对象里面有什么:
$ git cat-file -p 6bffd1c
040000 tree 645cf3cf0dedc40f52cb66dc152653e4adb143df file
100644 blob a497e7c6e2891fe4ebab8995e18f169c8f0ae882 hello.txt
通过以上信息,我们可以在得知,在完成提交后,会生成一个commit对象,一个commit对象代表一次提交。tree对象表示一个目录,而blob对象代表一个单独的文件。
现在我们将命令 git log
的结果以一种更明了的图形结构来表示其commit对象对应的结构:
git log --pretty=raw --graph
* commit 3f3c6f4f91e29e08c72874f1dc5309eefd998b66
| tree 6bffd1c96739426e0025993332c7b0cc63d94e00
| parent 505f1bcf709e4cc1d4f5c7d150718444fba652e6
| author JYGod <jiangyu@teddymobile.cn> 1527755326 +0800
| committer JYGod <jiangyu@teddymobile.cn> 1527755326 +0800
|
| second commit
|
* commit 505f1bcf709e4cc1d4f5c7d150718444fba652e6
tree 07ed5a7aebb914e3a02edf6d622b82d364037e3c
author JYGod <jiangyu@teddymobile.cn> 1526969349 +0800
committer JYGod <jiangyu@teddymobile.cn> 1526969349 +0800
first commit
对应的数据结构如下图所示: