【发布时间】:2020-10-25 01:04:33
【问题描述】:
我花了很多时间来清楚地了解“Git 中的工作目录” 它是一个特定的文件夹或目录吗?还是目录的一个版本?谁能帮我理解这个概念。 如果我在本地创建一个目录“mydir”怎么办 然后我运行:git init。 谢谢
【问题讨论】:
我花了很多时间来清楚地了解“Git 中的工作目录” 它是一个特定的文件夹或目录吗?还是目录的一个版本?谁能帮我理解这个概念。 如果我在本地创建一个目录“mydir”怎么办 然后我运行:git init。 谢谢
【问题讨论】:
在 Git 中,短语 working directory 曾 是 working tree 的同义词。它不再是,因为您的操作系统也可能使用短语工作目录(通常在前面加上第三个单词,作为当前工作目录)。现代 Git 尝试尽可能多地使用短语 working tree,尽管有时会缩短为 work-tree 或 worktree,如 @比如987654322@。
在您的操作系统中,当他们使用短语当前工作目录时,这是指您当时正在工作的文件夹或目录1。这可能在您的工作树中。
在 Git 中,短语 working tree 指的是操作系统维护的目录和文件,其中包含 您的 文件副本。这些是你的,可以随心所欲地处理:Git 只是从提交的文件中填充。
如果我在本地创建一个目录“mydir”然后我[运行]:
git init
让我将其改写为以下一系列 shell 命令:
$ mkdir mydir
$ cd mydir
$ git init
mkdir 在您当前的工作目录中创建一个新的空目录。然后cd 进入这个空目录,所以现在./mydir 是您当前的工作目录。 git init 命令运行时,它自己的当前工作目录就是这个空目录。
由于在您运行git init 时目录mydir 为空,Git 将在此mydir 目录中创建一个名为.git 的隐藏目录/文件夹。这个隐藏目录包含 repository 本身。存储库由许多实现多个数据库的文件和目录组成:
一个数据库是一个简单的key-value store,它使用哈希ID来定位内部Git 对象。这是组成 Git 存储库的两个主数据库中的主要(通常也是最大的)数据库。
一个数据库是另一个简单的键值存储,它使用名称作为键来存储哈希 ID,然后在第一个数据库中使用这些 ID。这是构成 Git 存储库的辅助数据库。这个特定数据库在当前版本的 Git 中的实现往往有点狡猾:它过于依赖您的操作系统。在 macOS 和 Windows 上,它往往有点缺陷。 Git 中正在进行的工作是用适当的数据库实现来替换它,这将消除这个问题。
除了这两个主要数据库之外,存储库还包含许多辅助文件,包括 Git 的 index(又名 staging area)。不过,这里最重要的一点是,所有这些实体都位于 .git 目录中。
由于还没有提交,所以两个主数据库都是空的。此时,Git 的索引也是如此。
您的 work-tree 包含当前工作目录中的所有文件和目录除了 .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 的索引。2 最后一个命令, git commit,从您(提交的人)那里收集一些元数据,并写出 Git 的索引和此元数据,将结果存储在主数据库中,以创建新的提交。
一旦您完成了这个新的初始提交(存储库中的第一次提交),分支名称就可能存在。在此之前它们不能存在,因为每个分支名称必须拥有一个有效的现有哈希 ID,并且未来提交的哈希 ID 是不可预测的。3 现在有 一个 提交,这是任何分支名称都可以保存的唯一哈希 ID。4
随着时间的推移,您将向存储库添加越来越多的提交。 (一般来说,drop 提交是非常罕见的,除了 git rebase 用新的和改进的提交替换提交的方式。这并非不可能,只是很难。)因此,每个新提交都会添加到存储库。
存储库本身包括:
提交对象,实际上是大数据库中的所有对象,都是严格只读的。没有什么也没有人可以改变它们。不过,它们的形式只对 Git 本身直接有用。
克隆存储库包括复制两个数据库,虽然 names 数据库仅被部分复制,并且在克隆过程中被更改。
同时,您的 工作树 是 Git extract 提交的地方,将仅对 Git 直接有用的东西变成了读取的内容-only——变成你可以使用和修改的东西。这些是你的文件。这就是你在工作树中工作的方式。您可以使用结果来更新 Git 的索引,然后使用 Git 的索引来创建一个 new 提交,它会添加到存储库而不更改存储库中已经存在的任何内容in .
1在操作系统级别,术语文件夹和目录是同义词。 Git 本身不存储 文件夹或目录:它只存储名称可能包含嵌入斜杠的文件,例如path/to/file.ext。这就是一个单一的文件名。您的操作系统可能会强制您首先创建一个名为 path 的文件夹,然后在该文件夹中创建一个名为 to 的文件夹,然后才使用组合的 path 和 to 文件夹在该路径中创建一个名为 file.ext 的文件。 当前工作目录可以更改为path,这样您就可以使用名称to/file.ext,而不是path/to/file.ext,甚至可以更改为path/to,这样您就可以使用名称@ 987654354@。在所有情况下,Git 都会在内部使用名为path/to/file.ext 的存储文件。所以您的当前工作目录是一个操作系统概念,指的是您如何在操作系统维护的文件夹中移动。
2从技术上讲,索引实际上并不直接保存 文件。它保存文件的 Git blob 对象 哈希 ID,它提供键值对象数据库的键,以便 Git 可以查找文件的内容以及 名称 文件(带有(正向)斜杠)和一些附加信息。 Blob 对象包含文件内容的压缩和去重副本。
这种重复数据删除,以及准备提交文件的是 git add 的事实,意味着 git commit 会运行得非常快,因为它不需要为提交做任何准备:它只是永久保存已存储在索引中的 blob 对象。
3提交的哈希 ID 是提交完整内容的加密校验和。内容不仅包括保存的源文件(作为内部 Git tree 对象),还包括确切的日期和时间戳。由于我们甚至不知道您将来会提交什么,更不用说确切何时您将提交它,我们无法计算未来的哈希 ID 将是什么。你可能知道什么你会承诺,这会让你更接近;但除非你确切地知道何时你会提交它,否则你也不知道哈希 ID。
4特别是分支名称受到限制:它们可能只包含一个提交哈希 ID。标签名称可以包含 Git 的四种内部对象类型中的任何一种的哈希 ID。 (通常,标签名称要么持有提交哈希 ID,要么持有新创建的带注释标签对象的哈希 ID,后者又持有提交哈希 ID。)其他类型的名称可能有自己的约束。
【讨论】: