¿Git 中的工作目录实际上是什么?



我花了很多时间来清楚地了解"Git 中的工作目录" 它是特定的文件夹还是目录?还是目录的版本?谁能帮助我理解这个概念。 如果我在本地创建一个目录"mydir"怎么办 然后我运行:git init。 谢谢

在 Git 中,短语工作目录曾经工作树的同义词。 它不再存在,因为短语工作目录也可能被您的操作系统使用(通常在前面有第三个单词,作为当前工作目录)。现代 Git 试图尽可能多地使用短语工作树,尽管这有时被缩短为work-treeworktree,例如在git worktree add中。

在您的操作系统中,当他们使用短语当前工作目录时,这是指您当时正在使用的文件夹或目录1。 这可能在您的工作树中。

在 Git 中,短语工作树是指操作系统维护的目录和文件,用于保存文件副本。这些是你的,可以随心所欲地处理:Git 只是从提交的文件中填充它们

如果我在本地创建一个目录"mydir",然后我[运行]:git init

让我将其改写为以下一系列 shell 命令:

$ mkdir mydir
$ cd mydir
$ git init

mkdir将在当前工作目录中创建一个新的空目录。 然后,cd进入此空目录,因此现在./mydir的是当前的工作目录。git init命令运行时,其自己的当前工作目录是这个空目录。

由于您运行git init时目录mydir为空,Git 将在此mydir目录中创建一个名为.git的隐藏目录/文件夹。 此隐藏目录包含适当的存储库。 存储库由许多实现多个数据库的文件和目录组成:

  • 一个数据库是一个简单的键值存储,它使用哈希 ID来查找内部 Git对象。 这是组成 Git 存储库的两个主数据库(通常是最大的)数据库。

  • 一个数据库是另一个简单的键值存储,它使用名称作为键来存储哈希 ID,然后在第一个数据库中使用。 这是构成 Git 存储库的辅助数据库。 这个特定数据库在当前版本的 Git 中的实现往往有点狡猾:它过于依赖您的操作系统。 在macOS和Windows上,它往往有点缺陷。 Git 中正在进行工作,用适当的数据库实现来替换它,这将消除这个问题。

  • 除了这两个主要数据库之外,存储库还包含许多辅助文件,包括 Git 的索引(又名暂存区域)。 不过,这里最重要的一点是,所有这些实体都位于.git目录中。

由于还没有提交,因此两个主数据库都是空的。 在这一点上,Git 的索引也是如此。

您的工作树由当前工作目录中的所有文件和目录组成,但保存 Git 文件的.git目录除外。 由于您的工作树是您的,并且由您的操作系统(而不是由 Git)维护,您现在可以在此处创建您喜欢的任何文件。

在某些时候,你会希望让 Git 创建一个新的提交。 这将是存储库中的第一次提交。 要创建此提交,您将使用git add将要进入此初始提交的文件添加到 Git 的索引/暂存区域中。git add程序的工作原理是将工作树文件复制到 Git 的索引中。 因此,由于操作系统的当前工作目录mydir目录,您现在可以只创建一些文件:

$ echo "repository for project X" > README
$ git add README
$ git commit

此处的echo命令在工作树中创建一个名为README的新文件。git add命令获取工作树文件,对其进行压缩和 Git 化,使其准备好存储在新的提交中,并将存储的文件写入 Git 的索引中。阿拉伯数字最后一个命令git commit从您(提交者)那里收集一些元数据,并写出 Git 的索引和这些元数据,将结果存储在主数据库中,以创建新的提交。

一旦您进行了这个新的初始提交(存储库中的第一次提交),分支名称就可能存在。 在此之前,它们不能存在,因为每个分支名称必须保存一个有效的现有哈希 ID,并且未来提交的哈希 ID 是不可预测的。3现在有一个提交,这是任何分支名称都可以保存的唯一哈希 ID。

随着时间的推移,您将向存储库添加越来越多的提交。 (一般来说,很少会删除提交,除了例如,git rebase用新的和改进的提交替换提交的方式。 这不是不可能,只是很难。 因此,每个新提交都会添加到存储库中

然后,存储库本身包括:

  • 保存提交和其他对象的数据库,以及找到它们的名称;
  • Git 的索引,用于保存你提议的下一次提交;和
  • 您和/或 Git 可能发现有用的其他维护项目。

提交对象,实际上大数据库中的所有对象,都是严格只读的。 没有什么,也没有人可以改变它们。 不过,它们的形式只对 Git 本身直接有用。

克隆存储库包括复制两个数据库,尽管名称数据库仅部分复制,并在克隆过程中发生更改。

同时,你的工作树是你进行 Git数据提取提交的地方,将只对Git直接有用的东西(只读)变成你可以使用和修改的东西。 这些是你的文件。 这就是你在工作树中做工作的方式。 您可以使用结果更新 Git 的索引,然后使用 Git 的索引创建一个新的提交,该提交将添加到存储库中,而无需更改存储库已存在的任何内容。


1在操作系统级别,术语文件夹目录是同义词。 Git 本身不存储文件夹或目录:它只存储名称可能包含嵌入斜杠的文件,例如path/to/file.ext. 这都是一个文件名。 您的操作系统可能会强制您先创建一个名为path的文件夹,然后在该文件夹中创建一个名为to的文件夹,然后才使用组合的pathto文件夹在该路径中创建名为file.ext的文件。当前工作目录可以更改为path,以便您使用名称to/file.ext而不是path/to/file.ext,甚至可以更改为path/to以便使用名称file.ext。 在所有情况下,Git 将在内部使用名为path/to/file.ext存储文件。 因此,您当前的工作目录是一个操作系统概念,指的是您在操作系统维护的文件夹中的移动方式。

2从技术上讲,索引实际上并不直接保存文件。 相反,它保存文件的 Git blob 对象哈希 ID,该 ID 提供键值对象数据库的键,以便 Git 可以查找文件的内容,以及文件名(使用(正斜杠)和一些附加信息。 Blob 对象保存文件内容的压缩和重复数据删除副本。

这种重复数据消除,以及git add为文件做好准备的事实,意味着git commit将运行得非常快,因为它不需要为提交准备任何内容:它只是永久保存已存储在索引中的 blob 对象。

3提交的哈希 ID 是提交完整内容的加密校验和。 内容不仅包括保存的源文件(作为内部 Git对象),还包括确切的日期和时间戳。 由于我们甚至不知道您将来会提交什么,更不用说您何时提交它了,因此我们无法计算未来的哈希 ID 会是什么。 你可能知道你会犯什么,这会让你更接近;但除非你确切地知道何时提交它,否则你也不会知道哈希 ID。

4分支名称尤其受到约束:它们只能保存一个提交哈希 ID。 标记名称可以保存 Git 的四种内部对象类型中的任何一种的哈希 ID。 (但是,通常,标签名称包含提交哈希 ID 或新创建的带注释的标记对象的哈希 ID,而该对象又包含提交哈希 ID。 其他类型的名称可能有自己的约束。

最新更新