一个 .git 目录,领悟 Git 的强大!

简介: Git 是一个强大的工具,但是使用起来却不是很友好。如果程序员们能够真正花时间去理解 Git 的构成,将会避免很多不必要的麻烦。

Git 是一个强大的工具,但是使用起来却不是很友好。如果程序员们能够真正花时间去理解 Git 的构成,将会避免很多不必要的麻烦。


以下为译文:


初学 Git 就像一个不懂当地语言的人来到一个陌生的国家——如果你知道自己在哪,该去哪里,那还好。一旦你迷路了,那麻烦就大了。


网上有很多学习 Git 基本命令的文章,但是本文并不属于这一类文章。我在此处将尝试提供一个不同的学习思路。


初学者一般都很害怕 Git,很难不怕。毫无疑问,Git 是一个强大的工具,但是使用起来却不是很友好。使用 Git 要理解很多新的概念,将文件作为命令参数和不作为参数两者的含义大相径庭。


我认为要想克服这些困难,不仅要学习 Git 的 commit 和 push 的用法。如果我们能够真正花时间去理解 Git 的构成,将会避免很多不必要的麻烦。


一、研究 .git 目录


好的,我们现在开始吧。


当你通过 git init 创建 git 仓库时, git  就会创建 .git 目录。该目录包含让 git 能够正常工作所需的所有信息。直白点说,如果你不想在项目中继续使用 git ,直接将 .git 目录删除只保留项目文件即可。但是为什么这样做就可以呢?


下面是你第一次提交后 .git 文件夹的样子:

微信图片_20220414194635.png


  • HEAD
    后面再讲。


  • config (配置)
    该文件包含你的仓库配置,比如远程的 url ,你的邮箱和用户名等。每次你在控制台使用 git config... 都会对这里产生影响。


  • description(描述)
    供 gitweb ( github  的一种前身) 使用,显示仓库的描述。


  • hooks (钩子)
    这是一个有趣的特性。Git 提供了一套脚本,可以在每个有意义的 Git 阶段自动运行。这些被称为钩子的脚本可以在提交 (commit)、变基 (rebase)、拉取 ( pull ) 操作的前后运行。脚本命预示着它的执行时机。如我们可以编写 pre-push 的作为钩子,进行推送代码前的检查。


  • info (信息)
    你可以将不想被 git 管理的文件记录到 .gitignore 文件中。排除文件的意思是不想共享这个文件。例如你不想共享你的 IDE 自定义配置,将其添加到 .gitignore 文件中即可。


二、一次提交包含哪些内容?


每次你创建一个文件,并追踪它,git 都将把文件进行压缩并存储在自己的数据结构中。被压缩的对象将具有唯一的名称和 hash 值,并将存储到对象 (object) 目录中。


在研究对象目录之前,我们必须明白一次提交的含义是什么。你可能会说,一次提交就是当前工作目录的一个快照,但事实远不止如此。


实际上,当你提交时,git 通过下面两个步骤对你的工作目录创建快照:


  • 如果文件没啥变化,git 只是将压缩的文件(哈希值)添加到快照中。


  • 如果文件发生了变化, git 将对其进行压缩并将其存储在 object 文件夹。最终,将这个压缩文件的名称(哈希值)添加到快照中。


这里给出一个简化的过程,实际上整个过程有点复杂,将在以后的文章中给出详细的介绍。关注微信公众号:Java技术栈,在后台回复:git,可以获取我整理的 N 篇最新 Git 教程,都是干货。


一旦快照被创建出来,它将会被压缩,以哈希值命名。那么这些压缩的对象存在哪里呢?他们被存在 object 文件夹中。

微信图片_20220414194843.png

这是我创建了一个空的文件  1.txt 并提交后 object 文件夹的样子。请注意,如果你的文件哈希值为 "4cf44f1e…",git 会将其存储到 "4c"子目录中,并将其命名为"f44f1…"。这个小技巧,将 /objects 目录的数量减少到 255 个以内。


你要记住的是,一次提交包含 4 个部分:

  1. 工作目录快照名称(一个哈希值)。
  2. 一条评论/注释。
  3. 提交者信息。
  4. 父提交的哈希值。

如果我们解压提交的文件:

// 通过查看提交历史,你可以轻松地查询到提交的哈希值  

// 你都不需要复制完整的哈希值字符串,  

// 复制能够保证哈希值的唯一性的前面一段即可。  

git cat-file -p 4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828  


得到下面的内容:


tree 86550c31847e518e1927f95991c949fc14efc711  

author Pierre De Wulf <test\[@gmail.com\](mailto:pierredewulf31@gmail.com)> 1455775173 -0500  

committer Pierre De Wulf <\[test@gmail.com\](mailto:pierredewulf31@gmail.com)> 1455775173 -0500  


commit A  


正如预想的一样,我们看到了快照的哈希值、作者信息和提交的注释。

有两个非常重要的事项:


正如所预想的那样,快照的哈希 "86550…" 也是一个对象,你可以在对象文件夹中找到它。


因为这是第一次提交,所以没有父提交的哈希值。

那么,在快照中存的是啥呢?


git cat-file -p 86550c31847e518e1927f95991c949fc14efc711  


100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file_1.txt  


我们找到之前存储的最后一个对象,也是我们快照中的唯一的一个对象。它是一个 blob 对象,这是另外的知识点,不在这里讨论。


三、分支, 标签, HEAD 都一样


你现在已经了解到,git 中的所有内容都可以通过正确的哈希值来获取到。现在让我们聚焦于 HEAD。那么什么是 HEAD?Git 高级用法,喜欢就拿去用。关注微信公众号:Java技术栈,在后台回复:git,可以获取我整理的 N 篇最新 Git 教程,都是干货。

cat HEAD  

ref: refs/heads/master  


HEAD 不是一个哈希,HEAD 可以理解为指向你正在使用的分支的顶端的指针。我们接下来看下 refs/heads/master:


cat refs/heads/master  

4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828  


看起来眼熟吗?这和我们第一次提交的哈希值相同。这表明分支 ( branch) 和标签 (tag) 只不过是一个指向提交的指针。这就意味着,即使你删掉了你要删除的分支和标签,他们指向的提交依然还在那里,只不过删除后难获取这些提交更困难一些。


如果你想了解更详细的内容,可以通过 git book 来学习。


目录
相关文章
|
开发工具 git
vscode编辑器里怎么显示.git隐藏文件夹到目录里
vscode编辑器里怎么显示.git隐藏文件夹到目录里
247 0
|
存储 开发工具 git
.git 目录中有什么?
.git 目录中有什么?
55 2
|
存储 开发工具 git
git中怎样忽略.idea/文件和目录
git中怎样忽略.idea/文件和目录
184 0
|
开发工具 git
将本地目录推送到Git远程仓库
将本地目录推送到Git远程仓库
|
开发工具 git
git 排除已经提交的文件目录
如果你已经把一个文件夹提交到了 Git 仓库中,但是后来发现这个文件夹不应该被提交,可以按照以下步骤排除已提交的文件夹: 在文件夹的根目录下创建一个名为 .gitignore 的文件。 编辑 .gitignore 文件,添加需要排除的文件夹的名称,以及其他需要排除的文件或文件类型,每个名称占一行。 执行以下命令,将 .gitignore 文件提交到 Git 仓库中:
527 0
|
存储 开发工具 文件存储
Git托管项目的.git目录下都有什么?
我们在使用`git`托管项目代码时,如果是新建项目需要通过`git init`命令在项目根目录下初始化`.git`目录来实现后续的代码托管管理,如果直接从代码仓库拉取代码则会自动创建`.git`目录与远程仓库进行绑定。
|
开发工具 git
同事偷偷改了git目录让我跑不起项目
由于当年太年轻,资历不够深!!!导致文件命名不规范,现在想更正文件夹名字(common => COMMON),结果发现一个很奇特的现象!git 对文件(夹)名的大小写不敏感!!!!引发了一些问题。最终经过查阅资料得以解决。
同事偷偷改了git目录让我跑不起项目
|
开发工具 git
GIT上传服务器同步到web目录
GIT上传服务器同步到web目录
167 0
GIT上传服务器同步到web目录
|
开发工具 git Windows
SVN / Git提交空目录 / 空文件夹问题解决方案
在windows操作系统下面用bat实现,遍历空目录然后给空目录添加空的index.html
537 0
SVN / Git提交空目录 / 空文件夹问题解决方案