【发布时间】:2020-09-14 17:52:29
【问题描述】:
昨天我开始学习 git。但是看到两个相互矛盾的存储库定义,我感到很困惑。
第一个:存储库是包含您的项目的目录。一种 存储库由提交组成。
第二个:存储库是项目中的 .git 文件夹。
这两个陈述实际上传达了同样的东西吗?那么他们是怎么做到的呢?
我已经看到了 .git 隐藏文件夹,这肯定不是我的项目。
【问题讨论】:
标签: git version-control repository
昨天我开始学习 git。但是看到两个相互矛盾的存储库定义,我感到很困惑。
第一个:存储库是包含您的项目的目录。一种 存储库由提交组成。
第二个:存储库是项目中的 .git 文件夹。
这两个陈述实际上传达了同样的东西吗?那么他们是怎么做到的呢?
我已经看到了 .git 隐藏文件夹,这肯定不是我的项目。
【问题讨论】:
标签: git version-control repository
这两个定义都过于关注存储库在本地文件系统上的样子。
从概念上讲,存储库是版本控制的文件树。它包含不同时间点和同一项目的不同开发分支的快照(或“提交”)。
在本地克隆存储库时,所有内容都包含在一个文件夹中。重建所有不同快照所需的数据位于 .git 子文件夹中。文件夹的其余部分代表项目的某个快照,以及您当前对其进行的任何未提交的更改。在任何时候,您都可以决定通过“提交”来创建新快照。用户可以通过向远程存储库推/拉快照来共享快照。
快照链接在一起,所以如果你得到一个,那么你也递归地得到它所基于的所有其他快照。这使您可以检查导致该状态的项目的整个历史。
【讨论】:
作为Wim Coenen put it,第二个定义——存储库是.git 目录中的东西——侧重于组织。
但是,从形式上讲,我必须同意第二个定义。剩下的区域——你进行工作的区域——不是存储库本身的一部分。它只是在存储库旁边。
原因是.git 文件夹内的东西是Git 的。你可以看看它,如果你了解 Git 的内部结构——随着 Git 的发展,随着时间的推移,它会从一个 Git 版本变化到另一个版本——你甚至可以直接在此处编辑内容。但总的来说,你应该把这些东西留给 Git 自己。
.git 文件夹中不的文件是你的。你可以对他们做任何你喜欢的事情。当您提出要求时,Git 会填充您的工作区域。
那么,简短的版本是你在你的工作树中工作。这个区域是你的,随心所欲。然后在不同的时间点告诉 Git:做某事。那某物可以:
如果您使用git worktree 命令,那么您的 工作区(不属于存储库的一部分)和 Git 的实际保存存储库的区域之间的区别会变得更加重要,首先在 Git 2.5 中添加。特别是,您可以使用git worktree add 创建额外的工作树。每个这样的工作树都不在存储库中,事实上,当你完成它时,你可以简单地删除这样的工作树。
(Git 将您的工作区称为工作树或工作树。这就是为什么添加新工作树的命令是git worktree add。)
Git 本身的主题是 Git 存储 commits。每个提交依次存储文件。实际上,每个提交都包含 所有 文件的完整快照。 Git 的存储文件使用重复数据删除,因为大多数提交大多持有与其他提交相同的文件版本。它们还以特殊的、只读的、仅限 Git 的格式存储。只有 Git 可以真正读取这些文件。这就是 Git 将文件提取到您的工作树的原因。
特别奇怪的部分是,当 Git 进行新提交时——这是你让 Git 存储更新文件的方式,在你更新它们之后——它会从 不是的副本中生成它们> 你的工作树中的副本!如果你曾经使用过 Mercurial,它在其他方面很像 Git,这可能有点令人费解。在 Mercurial 中,hg commit 从工作树中的文件进行新的提交。这是简单明了的。但是git commit 从 Git index 中的文件而不是工作树中的文件进行新提交。您必须继续使用 git add 将您更新的所有文件复制回 Git 的索引中。
因此,Git 的 index(Git 也将其称为 暂存区)是保存您提议的下一次提交的内容。在易于使用的 Mercurial 中,您的工作树包含您提议的下一次提交。在 Git 中,提议的下一个提交开始与当前提交匹配。当您更改工作树中的文件时,您必须将更改的文件复制回 Git 的索引,以更改建议的下一次提交。
(Git 进行新提交的方法为您提供了在 Mercurial 中难以实现的灵活性,但代价是需要大量 git add 命令。)
注意:在现代 Git 中,可以使用 git init --separate-git-dir 将 Git 的存储库(.git 文件夹)从您的工作树中分离出来。不过,我不知道有谁在日常工作中使用它。
【讨论】:
git clone 创建了一个新项目目录,然后在该项目目录中创建.git 目录,它“感觉”项目和存储库是一回事。从某种意义上说,它们是:这是一个带有存储库的项目。但是因为它们可以分开(例如git init --separate-git-dir),它们确实不是相同的。它们只是由一个git clone 命令创建的——如果你使用git clone。
git init,它不会“感觉”Git“拥有”项目目录。但是当你使用git clone 制作项目目录时,它“感觉不一样”。