Py学习  »  Git

如何将目录和子目录同时添加到Git

syaifulhusein • 3 年前 • 1347 次点击  

我想立即将包含子目录的目录从我的计算机推送到GitHub。

我的文件夹结构:

parent_folder
  |_ child_folder_1
  |_ child_folder_2
  |_ etc

当我 git init 转到父文件夹并尝试 git add . 我发现了一个错误:

warning: adding embedded git repository: Child_folder_1
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint:
hint:   git submodule add <url> Child_folder_1
hint:
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint:
hint:   git rm --cached Child_folder_1
hint:
hint: See "git help submodule" for more information.

这不仅发生在一个子文件夹上,而且发生在所有子文件夹上。这是因为子目录也包含git吗?那么我该怎么解决这个问题呢? 提前谢谢。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/130002
 
1347 次点击  
文章 [ 1 ]  |  最新文章 3 年前
torek
Reply   •   1 楼
torek    3 年前

Git不存储 目录 .Git商店 文件夹 ,或者更准确地说,Git商店 承诺 (然后存储文件——参见下面的挑剔区别)。但在你的情况下,问题是这些文件 已经在另一个Git存储库中 因此Git不会将它们添加到 存储库。

这是因为子目录也包含git吗?

更准确地说,这是因为这些子目录 Git存储库(有点像;请参阅下面的挑剔区别)。

那么我该怎么解决这个问题呢?

你必须立即(在你真正理解所有后果之前)做出一个具有深远影响的决定:

  • 你想用Git的吗 子模块
  • 你想吗 删除其他存储库 这样你就可以把这些文件直接存储在 仓库?

你需要知道的挑剔的区别

笨蛋 存储库 主要是一系列 承诺 .我们通常通过 分支机构名称 ,尽管这条规则也有例外。 克隆 存储库复制该存储库的所有(或至少大部分)提交,但 不复制其分支名称 .相反,我们的GitTour软件在创建和填充我们的存储库时,会读取另一个存储库的 树枝 命名并将其更改为 远程跟踪名称 .

因此,存储库本身主要由两个数据库组成(在此之后,添加了许多辅助内容,以使它们更可用)。其中一个,通常是最大的,持有commitsGit称之为 提交对象 有时还会加上Git需要的其他内部Git对象。这个对象数据库是一个简单的 key-value store 其中 钥匙 哈希ID: 巨大丑陋的字母和数字字符串,实际上是十六进制数,是加密校验和函数的输出。另一个数据库保存 姓名: 分支名称、标记名称、远程跟踪名称等等。每个名字都适用 散列ID;分支机构的名称尤其重要 犯罪 散列ID,因此让我们找到这些特定的提交。

每个 犯罪 反过来又有两件事:

  • 每个提交都有一个 每个文件的完整快照 。这些文件以特殊、只读、仅Git、压缩和消除重复的形式存储。它们不是普通文件,它们的名称中嵌入了前斜杠,例如 path/to/file.ext ,甚至在窗户上;它们区分大小写,即使您使用的是不区分大小写的Windows或macOS系统;等等

  • 每个提交也包含一些 元数据: 关于那个特别的承诺的信息。这包括提交人的姓名和电子邮件地址。它包括几个日期和时间戳,这有助于使每个提交都是唯一的。而且,对于Git的内部操作来说至关重要的是,每个提交都包含一个 以前的 提交哈希ID。

大多数提交中的前一个提交列表只有一个条目长,因此每个提交只记住其(单个)的原始散列ID 父母亲 犯罪这会将提交形成向后指向的链,其中 最近的 用一些大而丑陋的随机散列ID提交;我们就叫它吧 H — 指向 一些早期承诺:

            <-H

让我们把上一个提交称为“提交”,它的真实名称也是一个大而丑陋的随机散列ID G 这样我们就可以讨论它,并把它吸引进来:

        <-G <-H

犯罪 G ,作为提交,存储一些甚至更早提交的哈希ID F ,等等:

... <-F <-G <-H

每个提交还具有每个文件的完整快照,尽管有重复数据消除功能,以便 G 与中的文件完全匹配 H ,存储库中实际上只有该文件的一个副本。(Git通过哈希和它所称的 水滴状物体 ,但你通常不需要在意。)

通过 比较 中的快照 G 在这方面 H ,Git可以告诉您哪些文件是相同的——可能是大多数——哪些文件是不同的。这个 git diff , git show git log -p 命令都可以进行这种比较:它们将显示不同的文件,默认情况下,还会显示一个将左侧文件更改为右侧文件的配方。所以比较 G vs H 告诉您哪些文件发生了更改,以及发生了什么 那些文件。 H 但仍然存储完整的快照:为了找出发生了什么变化,Git必须找到 G .它能做到 因为 H 指向 G .

你不能 使用 直接提交,因为 只读,而且实际上只有Git可以读取。你也无法完成任何新工作,因为它是只读的。为了解决这个问题,我们实际上并不直接使用commit。相反,我们使用 git checkout git switch 摘录 承诺。这是:

  • 从之前的提交中删除所有以前提取的文件,然后
  • 从我们要移动的提交中提取所有文件

现在我们有了 可用的 每个文件的副本。这些可用的拷贝被Git称为 工作树 工作树 简而言之。

这些工作树文件就是您实际需要的文件 看见 合作 。它们是普通文件,由您的计算机以普通方式存储,因此它们位于目录中(有些人更喜欢这里的“文件夹”一词;任何一个都可以)。 这些文件不是Git格式的。 他们很可能已经来了 从…里面 吉特,维娅 git签出 但现在他们已经不在Git了。你对他们做的任何事情都不会影响Git。

如果您修改了这些文件,或者删除了一些文件,或者创建了新的文件,那么您最终必须告诉Git这一点。Git会将这些文件复制回它所称的 指数 集结区 .关于这一点有很多需要了解(你不能略过这些知识,因为这对理解a的概念至关重要。) 追踪 vs 未追踪 文件,以及如何 .gitignore 真的很管用),但我们这里不讨论这个问题,但你会跑的 git add ,然后最终 git commit .commit动词将使 当文件出现在Git的暂存区域时提交,然后更新当前文件 分支机构名称 将新提交记录为此分支上的最新提交。

这个 存储库本身 通常是 1. 被关在一个 .git 工作树顶层的目录(或文件夹)。也就是说,如果您的存储库处于 /Users/you/work/repo2 ,有一个 /Users/you/work/repo2/.git 包含 存储库 ,然后是 /用户/你/工作/报告2 这些文件是从 当前提交 你之前和他一起退房的 git签出 git交换机 .


1. 形容词 正常地 这是因为子模块和添加的工作树以及其他一些特殊情况会导致 文件 命名的 吉特先生 .Git在有令人信服的理由时就会使用这个技巧 移动 这个 吉特先生 目录 离开 从工作树上。子模块需要为一些其他丑陋的情况这样做;见下文。


子模块

Git的子模块在这张相对简单的图片上添加了一个褶皱。A. 子模块 在很大程度上,它只是一个包含在另一个存储库中的存储库。也就是说,有一个 吉特先生 某个Git存储库的工作树的子目录之一中的目录(或文件,如脚注1所示)。

如果Git存储库正在使用子模块,我们将该Git存储库称为 超级项目 超级项目和子模块仍然具有Git存储库的所有常规属性:它们在 吉特先生 目录(或在中找到的路径) 吉特先生 文件),以及签出提交的工作树。但是超级项目需要包含一些额外的内容,我们马上就会看到。

同时,子模块是 由超级项目控制 .子模块 仍然是一个存储库和工作树,所以仍然有提交,您可以签出一个。除了:通常 不要结账。你有 超级项目 那样做。

假设您克隆了一些Git存储库 R ,然后您现在查看您将使用的第一个提交 在里面 R ,以分支命名 B .以及 文件夹 这与承诺有关 B ,有一条指令,存储在commit for B 也就是说,实际上: 现在克隆并使用另一个Git存储库 另外 存储库是 s ,子模块。 R 现在是 超级项目 ,顾名思义。

为了克隆 s ,Git需要:

  • 要克隆的存储库的URL;
  • 工作树中用于签出的路径名 R ; 和
  • 提交哈希ID到 git checkout --detach 在里面 s 一旦制作完成 s .

Git从名为 gitlink ,并从同一gitlink获取提交哈希ID。gitlink来自commit B 然后进入索引/暂存区 R ,以及克隆 s ,Git在文件中查找gitlink的路径 .gitmodules 在commit中可以找到 B .此文件具有URL,因此超级项目Git能够运行正确的 git clone 命令:

git clone <url-for-S> path/to/s

例如,在你的情况下:

git clone <url> Child_folder_1

要使子模块克隆工作,必须有 .Git模块 用正确的信息归档。 这个 git submodule 命令是构建和维护这个 .Git模块 文件因此 Child_folder_1 作为子模块,必须运行:

git submodule add <repository-url> Child_folder_1

这将负责创建或更新 .Git模块 文件,这样克隆说明就会出现;这个 repository-url 你提供的就是 git克隆 我会晚一点回来。

如果你只是 git add Child_folder_1 Git补充道 gitlink 后期克隆所需指令集的一半。但这并没有增加 .Git模块 条目。这就是为什么会出现以下错误消息:

warning: adding embedded git repository: Child_folder_1
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint:
hint:   git submodule add <url> Child_folder_1
[snip]

这是在告诉您,您错误地添加了子模块。

为什么我们需要子模块?

我们没有。

然而,我们确实需要理解,Git存储库是 不允许包含另一个Git存储库 吉特先生 不会 添加名为 吉特先生 (或 .Git .GIT .giT ,或任何其他类似拼写)。更准确地说, 吉特先生 禁止将大写或小写字母混合作为名称组件。所以如果你 在存储库中有一个存储库, git添加 不会添加 文件夹 在这里相反,它将添加Git称之为 gitlink ,这将为您提供子模块样式的行为。Git的其他部分,包括 git status ,也不会抱怨这些文件未被跟踪(尽管它可能会提到 子模块存储库本身 在状态中)。

你可以,如果你愿意, 去除 这个 吉特先生 每个子模块工作树中的文件或目录。如果你这么做了,你就不再是这样了 对应Git存储库的工作树。相反,这些文件 计算机普通格式的普通文件现在是普通的,但是 未追踪 存储库工作树中的文件。我们可以用这个短语 这个 存储库,因为只有一个存储库。当你有子模块时,你正在使用两个或更多的存储库,所以每次有人说“存储库”,你必须停下来问:“等等, 哪一个 仓库?"

但是: 如果完全删除子模块存储库,则子模块存储库中不再有提交。 没有子模块存储库,因此没有提交。所以你的未追踪文件 这个 (顶层)存储库工作树是 只有副本 你所有的那些文件。你有 扔掉 所有的 另外 ,提交,这些文件的副本。

现在可以添加并提交 子文件夹1 保存当前工作目录(包括子目录)的(单个)存储库中的文件 子文件夹1 .但你只能 这个版本 这些文件的一部分。作为一个子模块,你会得到一个 gitlink 也就是说: 检查克隆后的提交(用哈希ID填写空白) ,以及 git克隆 副本 全部的 提交来自其他存储库,因此每个文件都有多个版本。

当你有一个子模块时,你可以 更新说明 在超级项目中。你可以说: 签出提交第二页(这次用一个不同的哈希ID填空) 这个 git submodule update 命令在超级项目中运行时,将切换到 那个 犯罪工作树文件将与其他提交文件匹配。

你甚至可以说 去除 那个子模块。这个 git子模块更新 命令将完全删除工作树文件。(以避免移除 吉特先生 目录,实际的 存储库 住在超级项目里 吉特先生 目录,这样就可以安全地删除它 吉特先生 文件。)

所以,你必须做出决定

子模块非常不方便,以至于很多人称它们为“哭泣模块”,因为它们让用户哭泣。但是他们做了一些没有他们你做不到的事情。你想做这件事吗?或者,您想要一个更简单的操作,在该操作中放弃 另外 Git存储库,只需 这是这些文件的一个版本 如果将子模块作为子模块添加到超级项目中,会是什么?

最简单快捷的方法就是放弃所有的历史。如果您今天不需要它,明天也不需要它,那么这会让您回到单一Git存储库的情况,而不需要子模块的复杂性。明天你就不会叫他们哭泣模块了。但如果你 如果你明天需要它,将来可能会因为昨天没有使用这些子模块而哭泣。

你现在有了我能给你的尽可能多的信息来做出这个决定。要么使用 git submodule add 将这些模块制作成适当的子模块,或移除 吉特先生 并将其添加为普通文件。