学会Git很简单(上)

作者: JYGod丶 | 来源:发表于2018-05-31 17:59 被阅读24次

    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 statusgit 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 带不同参数的区别:

    不同参数的 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
    

    对应的数据结构如下图所示:

    Git版本库结构图

    相关文章

      网友评论

      本文标题:学会Git很简单(上)

      本文链接:https://www.haomeiwen.com/subject/dcqcsftx.html