原副标题:20两分钟教你比如说Git!
Git 是最盛行的版管理工作软件,也是开发人员必不可少的专业技能众所周知。责任编辑就来教你 20 两分钟比如说 Git!
下列为原文:
虽然每晚你单厢加进Git,但也有可能想不通它的组织工作基本上原理。为何Git能管理工作版?基本上指示git add和git commit究竟在干嘛?
在这首诗中,我将用两个范例来说明Git的运转操作过程,协助你认知Git的组织工作基本上原理。
调用
让他们建立两个工程项目的产品目录,接着步入该产品目录。
$ mkdir git-demo-project
$ cd git-demo-project
如果想管理工作工程项目的版,那么他们应该做的第一件事情就是通过git init调用。
$ git init
git init只做了一件事情,那就是在工程项目的根产品目录下建立.git子产品目录来保存版信息。
$ ls .git
branches/
config
description
HEAD
hooks/
info/
objects/
refs/上述指示显示了.git子产品目录中的内容。
保存对象
接下来让他们建立两个新的空文件test.txt。
$ touch test.txt
接着把这个文件添加到Git代码库中,这一步将建立test.txt现有内容的两个副本。
$ git hash-object -w test.txt
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
在上述代码中,git hash-object指示将test.txt现有的内容压缩成二进制文件,并保存到Git中。该压缩文件叫做Git对象,保存在.git/objects产品目录中。
$ ls -R .git/objects
.git/objects/e6:
9de29bb2d1d6434b8b29ae775ad8c2e48c5391如上述代码所示,.git/objects产品目录下又多出了两个子产品目录,而且这个子产品目录名是上述哈希值的前两个字符。在这个子产品目录下有两个文件,文件名是上述哈希值中其余的38个字符。
让他们再来看看文件内容。
$ cat .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
上述代码输出的文件内容是一些二进制字符。你可能会问既然test.txt是空文件,又怎么会有这些内容呢?这是因为该二进制对象中还存储了一些元数据。
如果你想看看该文件原始的文本内容,那么应该使用git cat-file。
$ git cat-file -p e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
因为原文件为空,所以上述指示什么都没有显示。现在他们往test.txt文件中写点东西。
$ echo hello world > test.txt
这个文件的内容已经改变了,所以你需要再次把它保存为Git对象。
$ git hash-object -w test.txt
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
如上述代码所示,test.txt的哈希值已经随着文件内容的改变而发生了变化。同时还生成了新文件.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad。现在你能看到这个文件的内容了。
$ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
hello world
更新索引
当文件保存成二进制对象以后,你需要告诉Git哪个文件发生了变化。Git会在两个名叫“索引”(或阶段)的区域记录所有发生了变化的文件。接着等到所有的变更都结束后,将索引中的这些文件一起写入正式的版历史记录中。
$ git update-index –add –cacheinfo 100644 \
3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt上述指示记录了文件名test.txt、二进制对象名(哈希值)以及索引中文件的访问权限。
git ls-files指示能显示索引中当前的内容。
$ git ls-files –stage
100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0 test.txt
上述代码显示索引中只有两个test.txt文件,还显示了该文件的二进制对象名和访问该文件的权限。如果你知道该二进制对象名,就能查看.git/objects子产品目录中该文件的内容。
git status指示能输出更多可读的结果。
$ git status
Changes to submit:
The new file: test.txt
上述代码显示索引中只有两个新文件test.txt,该文件正在等候写入版的历史记录中。
git add指示
针对每个文件执行上述两个步骤非常繁琐。所以Git提供了git add指示来简化这些操作。
$ git add –all
上述指示相当于针对当前工程项目中所有发生了变化的文件执行上述两个步骤。
提交(Commit)
索引保存发生了变化的文件信息。等到修改完成,所有这些信息单厢被写入版的历史记录中,这相当于生成两个当前工程项目的快照。
工程项目的历史记录由不同时间点的工程项目快照组成。Git能将工程项目恢复成任何两个快照。在Git中“快照”有两个专门的术语,即“提交”(commit)。所以生成快照也能称之为完成提交。
下列所有“快照”的引用指的都是提交。
完成提交
首先,他们需要设置用户名和邮件地址。在你保存快照的时候,Git需要记录是谁执行的提交。
$ git config user.name “username”
$ git config user.email “Email address”
接下来,保存现有的产品目录结构。在责任编辑的前面他们讨论了保存对象只会保存两个文件,并不会记录文件之间的产品目录结构。
git write-tree指示能根据当前产品目录结构生成两个Git对象。
$ git write-tree
c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
在上述代码中,产品目录结构保存成了二进制对象,而对象的名字是哈希值。它也保存在.git/objects产品目录中。
让他们来看看该文件的内容。
$ git cat-file -p c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt
能看到,当前产品目录中只有两个文件test.txt。
这个所谓的快照就是保存当前的产品目录结构,以及每个文件相对应的二进制对象。之前的操作已经保存了文件结构,所以现在你需要把这个产品目录结构和一些元数据一起写入版的历史记录中。
git commit-tree能将产品目录树对象写入到版的历史记录中。
$ echo “first commit” | git commit-tree c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
在上述代码中,在提交时你需要提供提交的描述,而且你能通过echo “first commit”提供提交描述。git commit-tree指示会根据元数据以及产品目录树生成两个Git对象。现在,让他们来看看该对象的内容。
$ git cat-file -p c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
tree c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
author jam 1538889134 +0800
committer jam 1538889134 +0800
first commit
在上述代码中,第一行输出是对应于该快照的产品目录树对象,而第二行和第三行是有关作者和提交者的信息,最后一行内容是提交的描述。
通过git log指示他们还能查看某个快照的信息。
$ git log –stat c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
commit c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
Author: jam
Date: Sun Oct 7 13:12:14 2018 +0800
first commit
test.txt | 1 +
1 file changed, 1 insertion(+)
git commit指示
Git提供了git commit来简化上述提交操作。在保存到索引后,你只需要执行git commit指示,就能同时提交产品目录结构和描述,并生成快照。
$ git commit -m “first commit”
另外,还有两个指示也非常实用。
通过git checkout指示,他们能切换到某个快照。
$ git checkout c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
通过git show指示,他们能显示某个快照的所有代码变更。
$ git show c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
分支(branch)
然而,如果你使用git log指示来查看整个版的历史记录时,却无法看到刚刚生成的快照。
$ git log
上述指示输出为空。这是为何?这个快照刚刚不是写入到历史记录中了吗?
真相是:git log指示只能显示当前分支上的变化。虽然他们已经提交了这个快照,但是还没有记录这个快照属于哪个分支。
分支是快照的指针,分支的名字就是该指针的名字。虽然哈希值不可读,但是分支允许用户给快照起别名。另外,分支还会自动更新,如果当前分支是两个新的快照,那么这个指针会自动指向它。例如,主分支(master branch)有两个名为master的指针指向主分支当前的快照。
用户能为任何快照建立新指针。例如,如果你想建立两个新的fix-typo分支,那么只需建立两个名为fix-typo的指针,并指向两个快照。因此,在Git中建立两个新分支非常容易,而且开销非常低。
Git有两个特殊的指针HEAD,它始终指向当前分支中最新的那个快照。另外,Git还提供了快捷方式。例如,HEAD^指向HEAD之前的快照(父节点),而HEAD~6指向HEAD之前的第六个快照。
每个分支的指针都是两个文责任编辑件,存储在.git/refs/heads/产品目录中。文件的内容是它指向的快照的二进制文件名(哈希值)。
更新分支
下面他们将演示如何更新分支。首先,修改test.txt。
$ echo “hello world again” > test.txt
然后保存二进制对象。
$ git hash-object -w test.txt
c90c5155ccd6661aed956510f5bd57828eec9ddb
接下来,将该对象写入索引,并保存产品目录结构。
$ git update-index test.txt
$ git write-tree
1552fd52bc14497c11313aa91547255c95728f37
最后,提交产品目录结构,并生成两个快照。
$ echo “second commit” | git commit-tree 1552fd52bc14497c11313aa91547255c95728f37 -p c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
785f188674ef3c6ddc5b516307884e1d551f53ca
在上述代码中,他们能通过git commit-tree指示的参数-p来指定父节点,即以哪个快照为基础。
下面他们把快照的哈希值写入到.git/refs/heads/master文件中,并让master指针指向该快照。
$ echo 785f188674ef3c6ddc5b516307884e1d551f53ca > .git/refs/heads/master
现在,通过git log指示你能看到两个快照了。
$ git log
commit 785f188674ef3c6ddc5b516307884e1d551f53ca (HEAD -> master)
Author: jam
Date: Sun Oct 7 13:38:00 2018 +0800
second commit
commit c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
Author: jam
Date: Sun Oct 7 13:12:14 2018 +0800
first commit
git log指示的运转操作过程大致如下:
找到HEAD指针对应的分支。在上述示例中为master。
找到master指针指向的快照。在上述示例中为785f188674ef3c6ddc5b516307884e1d551f53ca。
找到父节点(即前两个快照)c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa。
等等,最后显示当前分支中所有的快照。
另外,上述我们曾提到分支指针是动态的,下述三个指示会自动覆盖分支指针。
Git commit:当前分支的指针将移动到新建立的快照上。
Git pull:在当前分支和远程分支合并后,指针会指向新建立的快照。
Git reset [commit_sha]:当前分支的指针将被复位到某个指定的快照上。
原文:
https://www.tutorialdocs.com/article/how-git-works.html
作者:Alex
译者:弯月,责编:郭芮
公开课预告
◆
文本分类
◆
在文本分类领域中的模型和算法有很多,那如何为你的文本分类问题选择合适的模型呢?本节公开课通过对比来阐述不同的算法、模型在实际的应用操作过程中的区别,以及在文本分类实践中所遇到的各种坑。