mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-08 23:14:06 +08:00
64 lines
18 KiB
HTML
64 lines
18 KiB
HTML
<div class="c-markdown doc-markdown"><div class="doc-postil"><div class="c-markdown"><h2>命名</h2></div></div><div class="doc-postil"><div class="c-markdown"><p>gittutorial-2 - Git 的教程介绍:第二部分</p></div></div><div class="doc-postil"><div class="c-markdown"><h2>概要</h2></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">git *</pre></div></div><div class="doc-postil"><div class="c-markdown"><h2>描述</h2></div></div><div class="doc-postil"><div class="c-markdown"><p>阅读本教程之前,您应该通过 gittutorial [7] 。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>本教程的目标是介绍 Git 体系结构的两个基本部分 - 对象数据库和索引文件,并向读者提供理解其余 Git 文档所需的一切。</p></div></div><div class="doc-postil"><div class="c-markdown"><h2>git 对象数据库</h2></div></div><div class="doc-postil"><div class="c-markdown"><p>让我们开始一个新项目并创建少量历史记录:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ mkdir test-project
|
||
|
||
$ cd test-project
|
||
|
||
$ git init
|
||
|
||
Initialized empty Git repository in .git/$ echo 'hello world' > file.txt
|
||
|
||
$ git add .$ git commit -a -m "initial commit"[master (root-commit) 54196cc] initial commit 1 file changed, 1 insertion(+)
|
||
|
||
create mode 100644 file.txt
|
||
|
||
$ echo 'hello world!' >file.txt
|
||
|
||
$ git commit -a -m "add emphasis"[master c4d59f3] add emphasis 1 file changed, 1 insertion(+), 1 deletion(-)</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>Git 响应提交的十六进制数字是什么?</p></div></div><div class="doc-postil"><div class="c-markdown"><p>我们在教程的第一部分看到了提交这样的名字。事实证明,Git 历史记录中的每个对象都以40位十六进制名称存储。该名称是对象内容的 SHA-1 散列; 除此之外,这确保了 Git 永远不会存储两次相同的数据(因为相同的数据具有相同的 SHA-1 名称),并且 Git 对象的内容永远不会改变(因为这也会改变对象的名称)。这里的7个字符的十六进制字符串就是这样的40个字符长的字符串的缩写。缩写可以用于任何可以使用40个字符串的地方,只要它们是明确的即可。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>预计在上面的例子中创建的提交对象的内容会生成与上面显示的不同的 SHA-1 哈希值,因为提交对象会记录创建时间和执行提交人员的姓名。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>我们可以用<code>cat-file</code>命令向 Git 询问这个特定的对象。不要复制这个例子中的40个十六进制数字,而是使用你自己版本的数字。请注意,您可以将其缩短为只有几个字符,以免键入所有40个十六进制数字:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git cat-file -t 54196cc2
|
||
|
||
commit
|
||
|
||
$ git cat-file commit 54196cc2
|
||
|
||
tree 92b8b694ffb1675e5975148e1121810081dbdffe
|
||
|
||
author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500initial commit</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>树可以引用一个或多个 “blob” 对象,每个对象都对应一个文件。另外,树还可以引用其他树对象,从而创建目录层次结构。您可以使用 ls-tree 检查任何树的内容(请记住,SHA-1 的足够长的初始部分也可以工作):</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git ls-tree 92b8b694100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad file.txt</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>因此我们看到这棵树里有一个文件。SHA-1 散列是对该文件数据的引用:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git cat-file -t 3b18e512
|
||
|
||
blob</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>“blob” 只是文件数据,我们也可以用 cat-file 来检查:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git cat-file blob 3b18e512
|
||
|
||
hello world</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>请注意,这是旧的文件数据; 所以 Git 在对初始树的响应中命名的对象是一棵树,其中包含第一次提交记录的目录状态的快照。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>所有这些对象都存储在 Git 目录下的 SHA-1 名称下:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ find .git/objects/.git/objects/.git/objects/pack.git/objects/info.git/objects/3b.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad.git/objects/92.git/objects/92/b8b694ffb1675e5975148e1121810081dbdffe.git/objects/54.git/objects/54/196cc2703dc165cbd373a65a4dcf22d50ae7f7.git/objects/a0.git/objects/a0/423896973644771497bdc03eb99d5281615b51.git/objects/d0.git/objects/d0/492b368b66bdabf2ac1fd8c92b39d3db916e59.git/objects/c4.git/objects/c4/d59f390b9cfd4318117afde11d601c1085f241</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>而这些文件的内容只是压缩数据加上一个标识它们的长度和类型的头文件。该类型是 blob ,树,提交或标记。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>最简单的提交是 HEAD 提交,我们可以从 .git / HEAD 找到:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ cat .git/HEAD
|
||
|
||
ref: refs/heads/master</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>正如你所看到的,这告诉我们我们当前正在使用哪个分支,并且它通过命名 .git 目录下的一个文件告诉我们这个文件,它本身包含引用一个提交对象的 SHA-1 名称,我们可以用它来检查猫文件:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ cat .git/refs/heads/master
|
||
|
||
c4d59f390b9cfd4318117afde11d601c1085f241
|
||
|
||
$ git cat-file -t c4d59f39
|
||
|
||
commit
|
||
|
||
$ git cat-file commit c4d59f39
|
||
|
||
tree d0492b368b66bdabf2ac1fd8c92b39d3db916e59
|
||
|
||
parent 54196cc2703dc165cbd373a65a4dcf22d50ae7f7
|
||
|
||
author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143418702 -0500committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143418702 -0500add emphasis</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>这里的“树”对象指的是树的新状态:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git ls-tree d0492b36100644 blob a0423896973644771497bdc03eb99d5281615b51 file.txt
|
||
|
||
$ git cat-file blob a0423896
|
||
|
||
hello world!</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>而“父”对象引用了之前的提交:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git cat-file commit 54196cc2
|
||
|
||
tree 92b8b694ffb1675e5975148e1121810081dbdffe
|
||
|
||
author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500initial commit</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>树对象是我们首先检查的树,而这个提交是不寻常的,因为它缺少任何父对象。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>大多数提交只有一个父,但是承诺有多个父也很常见。在这种情况下,提交表示合并,并且父引用指向合并分支的 HEAD 。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>除了斑点,树和提交之外,唯一剩下的对象就是一个“tag”,我们不在这里讨论; 有关详细信息,请参阅 git-tag [1] 。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>所以现在我们知道 Git 如何使用对象数据库来表示一个项目的历史记录:</p></div></div><div class="doc-postil"><div class="c-markdown"><ul class="ul-level-0 list-paddingleft-2" style="margin: 10px 0px 10px 20px;"><li><p>“commit”对象指的是表示历史中特定点上的目录树快照的“树”对象,并参考“父”提交来显示它们如何连接到项目历史中。</p></li></ul></div></div><div class="doc-postil"><div class="c-markdown"><ul class="ul-level-0 list-paddingleft-2" style="margin: 10px 0px 10px 20px;"><li><p>“树”对象表示单个目录的状态,将目录名称与包含文件数据的 “blob” 对象以及包含子目录信息的“树”对象相关联。</p></li></ul></div></div><div class="doc-postil"><div class="c-markdown"><ul class="ul-level-0 list-paddingleft-2" style="margin: 10px 0px 10px 20px;"><li><p>“blob”对象包含没有任何其他结构的文件数据。</p></li></ul></div></div><div class="doc-postil"><div class="c-markdown"><ul class="ul-level-0 list-paddingleft-2" style="margin: 10px 0px 10px 20px;"><li><p>在每个分支头部提交对象的引用存储在 .git / refs / heads / 下的文件中。</p></li></ul></div></div><div class="doc-postil"><div class="c-markdown"><ul class="ul-level-0 list-paddingleft-2" style="margin: 10px 0px 10px 20px;"><li><p>当前分支的名称存储在 .git / HEAD 中。</p></li></ul></div></div><div class="doc-postil"><div class="c-markdown"><p>请注意,顺便提一下,很多命令都以树为参数。但是,正如我们上面所看到的,树可以以许多不同的方式引用 - 通过树的 SHA-1 名称,引用树的提交的名称,引用其头部的分支的名称到那棵树等等 - 而且大多数这样的命令可以接受任何这些名字。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>在命令提要中,有时用 “tree-ish” 这个词来表示这样一个参数。</p></div></div><div class="doc-postil"><div class="c-markdown"><h2>索引文件</h2></div></div><div class="doc-postil"><div class="c-markdown"><p>我们用来创建提交的主要工具是<code>git-commit -a</code>创建一个提交,包括您对工作树所做的每个更改。但是,如果您只想对某些文件进行更改,该怎么办?或者只对某些文件进行某些更改?</p></div></div><div class="doc-postil"><div class="c-markdown"><p>如果我们看一下在封面下创建提交的方式,我们会看到创建提交的方式更加灵活。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>继续我们的测试项目,让我们再次修改 file.txt :</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ echo "hello world, again" >>file.txt</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>但是这次不是立即做出提交,而是让我们采取中间步骤,并沿途询问差异来跟踪发生的事情:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git diff--- a/file.txt+++ b/file.txt
|
||
|
||
@@ -1 +1,2 @@
|
||
|
||
hello world!+hello world, again
|
||
|
||
$ git add file.txt
|
||
|
||
$ git diff</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>最后的差异是空的,但没有新的提交已经完成,并且 head 仍然不包含新行:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git diff HEAD
|
||
|
||
diff --git a/file.txt b/file.txt
|
||
|
||
index a042389..513feba 100644--- a/file.txt+++ b/file.txt
|
||
|
||
@@ -1 +1,2 @@
|
||
|
||
hello world!+hello world, again</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>所以<code>git diff</code>比较头部以外的东西。它比较的东西实际上是索引文件,它以二进制格式存储在 .git / index 中,但其内容可以用 ls-files 检查:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git ls-files --stage100644 513feba2e53ebbd2532419ded848ba19de88ba00 0 file.txt
|
||
|
||
$ git cat-file -t 513feba2
|
||
|
||
blob
|
||
|
||
$ git cat-file blob 513feba2
|
||
|
||
hello world!hello world, again</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>所以我们<code>git add</code>做的是存储一个新的 blob ,然后在索引文件中加入一个引用。如果我们再次修改文件,我们会看到新的修改反映在<code>git diff</code>输出中:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ echo 'again?' >>file.txt
|
||
|
||
$ git diff
|
||
|
||
index 513feba..ba3da7b 100644--- a/file.txt+++ b/file.txt
|
||
|
||
@@ -1,2 +1,3 @@
|
||
|
||
hello world!
|
||
|
||
hello world, again+again?</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>使用正确的参数,<code>git diff</code>还可以显示工作目录和上次提交之间或索引和上次提交之间的区别:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git diff HEAD
|
||
|
||
diff --git a/file.txt b/file.txt
|
||
|
||
index a042389..ba3da7b 100644--- a/file.txt+++ b/file.txt
|
||
|
||
@@ -1 +1,3 @@
|
||
|
||
hello world!+hello world, again+again?$ git diff --cached
|
||
|
||
diff --git a/file.txt b/file.txt
|
||
|
||
index a042389..513feba 100644--- a/file.txt+++ b/file.txt
|
||
|
||
@@ -1 +1,2 @@
|
||
|
||
hello world!+hello world, again</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>在任何时候,我们都可以使用<code>git commit</code>(不带 “-a” 选项)创建一个新的提交,并验证提交的状态只包含索引文件中存储的更改,而不是仅存在于工作树中的更改。</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git commit -m "repeat"$ git diff HEAD
|
||
|
||
diff --git a/file.txt b/file.txt
|
||
|
||
index 513feba..ba3da7b 100644--- a/file.txt+++ b/file.txt
|
||
|
||
@@ -1,2 +1,3 @@
|
||
|
||
hello world!
|
||
|
||
hello world, again+again?</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>所以默认情况下<code>git commit</code>使用索引来创建提交,而不是工作树; 提交的 “-a” 选项告诉它首先用工作树中的所有更改更新索引。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>最后,值得关注<code>git add</code>索引文件的效果:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ echo "goodbye, world" >closing.txt
|
||
|
||
$ git add closing.txt</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>该功能的作用<code>git add</code>是将一个条目添加到索引文件中:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git ls-files --stage100644 8b9743b20d4b15be3955fc8d5cd2b09cd2336138 0 closing.txt100644 513feba2e53ebbd2532419ded848ba19de88ba00 0 file.txt</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>而且,正如您可以用 cat-file 看到的那样,这个新条目引用了该文件的当前内容:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git cat-file blob 8b9743b2
|
||
|
||
goodbye, world</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>"status" 命令是快速总结情况的有用方法:</p></div></div><div class="doc-postil"><div class="c-markdown"><pre class="prism-token token language-javascript">$ git status
|
||
|
||
On branch master
|
||
|
||
Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: closing.txt
|
||
|
||
|
||
|
||
Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory)
|
||
|
||
|
||
|
||
modified: file.txt</pre></div></div><div class="doc-postil"><div class="c-markdown"><p>由于 closing.txt 的当前状态被缓存在索引文件中,因此它被列为“要提交的更改”。由于 file.txt 在工作目录中的变化未反映在索引中,因此它被标记为“已更改但未更新”。此时,运行 “git commit” 会创建一个提交 clos.txt(及其新内容)的提交,但不会修改 file.txt 。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>此外,请注意,bare 会<code>git diff</code>显示对 file.txt 的更改,但不会增加 closing.txt ,因为索引文件中 closing.txt 的版本与工作目录中的版本相同。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>除了作为新提交的暂存区域之外,还在检出分支时从对象数据库填充索引文件,并且该文件用于保存涉及合并操作的树。有关详细信息,请参阅 gitcore-tutorial [7] 和相关手册页。</p></div></div><div class="doc-postil"><div class="c-markdown"><h2>接下来是什么?</h2></div></div><div class="doc-postil"><div class="c-markdown"><p>此时,您应该知道读取任何 git 命令的手册页所需的一切; 在 giteveryday [7] 中提到的命令是一个很好的开始。你应该能够在 gitglossary 中找到任何未知的术语[7]。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>Git 用户手册提供了更全面的 Git 介绍。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>gitcvs-migration [7] 解释了如何将 CVS 存储库导入到 Git 中,并展示了如何以类似 CVS 的方式使用 Git 。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>有关 Git 使用的一些有趣示例,请参阅 howtos。</p></div></div><div class="doc-postil"><div class="c-markdown"><p>对于 Git 开发人员,gitcore-tutorial [7] 详细介绍了涉及创建新提交的较低级 Git 机制。</p></div></div></div> |