Git 存储库混乱

Posted

技术标签:

【中文标题】Git 存储库混乱【英文标题】:Git repository confusion 【发布时间】:2020-09-14 17:52:29 【问题描述】:

昨天我开始学习 git。但是看到两个相互矛盾的存储库定义,我感到很困惑。

第一个:存储库是包含您的项目的目录。一种 存储库由提交组成。

第二个:存储库是项目中的 .git 文件夹。

这两个陈述实际上传达了同样的东西吗?那么他们是怎么做到的呢? 我已经看到了 .git 隐藏文件夹,这肯定不是我的项目。

【问题讨论】:

【参考方案1】:

这两个定义都过于关注存储库在本地文件系统上的样子。

从概念上讲,存储库是版本控制的文件树。它包含不同时间点和同一项目的不同开发分支的快照(或“提交”)。

在本地克隆存储库时,所有内容都包含在一个文件夹中。重建所有不同快照所需的数据位于 .git 子文件夹中。文件夹的其余部分代表项目的某个快照,以及您当前对其进行的任何未提交的更改。在任何时候,您都可以决定通过“提交”来创建新快照。用户可以通过向远程存储库推/拉快照来共享快照。

快照链接在一起,所以如果你得到一个,那么你也递归地得到它所基于的所有其他快照。这使您可以检查导致该状态的项目的整个历史。

【讨论】:

【参考方案2】:

作为Wim Coenen put it,第二个定义——存储库是.git 目录中的东西——侧重于组织

但是,从形式上讲,我必须同意第二个定义。剩下的区域——你进行工作的区域——不是存储库本身的一部分。它只是在存储库旁边

原因是.git 文件夹内的东西是Git 的。你可以看看它,如果你了解 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 文件夹)从您的工作树中分离出来。不过,我不知道有谁在日常工作中使用它。

【讨论】:

谢谢。这是一个非常详细且相对简单的解释。 为什么很多人把仓库称为项目目录本身? @Sharandeep:你得问他们?,但我认为这是一种心理混淆:因为git clone 创建了一个新项目目录,然后在该项目目录中创建.git 目录,它“感觉”项目和存储库是一回事。从某种意义上说,它们是:这是一个带有存储库的项目。但是因为它们可以分开(例如git init --separate-git-dir),它们确实不是相同的。它们只是由一个git clone 命令创建的——如果你使用git clone 请注意,如果您自己创建项目目录,用文件填充它,并在考虑提交之前做一些初步工作,然后只然后运行git init,它不会“感觉”Git“拥有”项目目录。但是当你使用git clone 制作项目目录时,它“感觉不一样”。 感谢您的建议和建议?

以上是关于Git 存储库混乱的主要内容,如果未能解决你的问题,请参考以下文章

Git存储库中的Git存储库[重复]

如何在某个 Git 存储库中获取 Git 存储库的名称?

如何将普通的 Git 存储库转换为裸存储库?

git-svn 多个 git 存储库到同一个 svn 存储库

如何从一个 Git 存储库迁移到另一个 Git 存储库?

git:使用(本地)远程存储库