如何将修改后的子模块“ git添加”到主模块中?

时间:2020-03-17 21:02:31

标签: git git-submodules git-add

我修改,添加,提交并推送了对子模块的更改,然后转到主模块目录并运行:

# git status
...
Changes not staged for commit:
...
modified:   deps/gr-d13 (modified content, untracked content)
...

# git add deps/gr-d13
(no errors)
# git status
...
Changes not staged for commit:
...
modified:   deps/gr-d13 (modified content, untracked content)
...

与以前完全相同。我的子模块未上演。为什么不呢?

主模块和子模块都在同一分支上。

1 个答案:

答案 0 :(得分:2)

让我们从在游泳池深处的潜水开始。这个:

modified:   deps/gr-d13 (modified content, untracked content)

表示您的超级项目Git做过:

(cd deps/gr-d13; git status)

查明子模块存储库的状态,当发现子模块存储库时,其子树的工作树中包含已修改的文件和未跟踪的文件。

如果要提交那些文件,则需要自己输入子模块存储库,并像使用任何Git存储库一样使用它。只需记住,它当前处于<​​em>分离式HEAD 模式,并且已签出特定的提交。该提交可能具有也可能没有关联的分支名称。如果没有,请记住您需要做什么。

一旦子模块中有新提交,就可以让超级项目引用该新提交。为此,请返回超级项目,然后运行git add deps/gr-d13。这将告诉超级项目Git执行(cd deps/gr-d13; git rev-parse HEAD)来找到正确的提交哈希ID,然后将该哈希ID记录在超级项目的索引中。

背景

请记住,子模块不过是第二个Git存储库。您的(顶级)Git存储库现在是一个 superproject 。在您的超级项目中,您所做的每个提交都列出了两件事:

  • 子模块存储库的路径名,在这种情况下为deps/gr-d13
  • 您的超级项目Git在使用时应使用的哈希ID:

    (cd $submodule; git checkout $hash)
    

    以便在指定的提交时强制子模块Git处于分离的HEAD 模式。

(超级项目应该也有一个.gitmodules文件,其中包含超级项目的新克隆才能运行创建该项目的git clone命令所需的信息。子模块存储库。该文件也应该在每个提交中。一旦存在子模块存储库,Git就不再需要.gitmodules文件来获取此信息。)

工作树中看到的文件是 not 提交的文件。 (提交的文件以特殊的,压缩的,只读的,仅Git的格式存储,作为提交快照的一部分。)与在任何Git存储库中一样,当您检出提交时,其文件将进入索引,然后从那里将它们复制出来,并扩展为有用的形式,扩展到工作树,以便您可以查看和使用它们。

您的超级项目内部没有任何子模块提交,只有子模块提交的 hash ID 。但是,用于超级项目存储库的工作树确实具有一个目录(或文件夹,如果您更喜欢该术语,则包含),其中包含.git 1 和子模块的工作树。这意味着子模块的工作树是超级项目工作树的子目录。

您可以随时使用:

cd deps/gr-d13

自行进入子模块存储库。如果这样做,则可以像使用任何存储库一样使用它。就像任何存储库一样,它具有提交,HEAD,索引和工作树。该子模块存储库唯一的特别之处在于,有一个外部存储库,有时(在被告知时)会对子模块执行cd并运行git checkout <hash>使其再次进入分离的HEAD模式。指定的提交。


1 在旧版本的Git中,该.git将是一个实际目录,其中包含子模块的存储库数据库(即不是工作树的所有内容)。在现代Git中,此.git将是一个纯文件。现在,Git将子模块存储库数据库“吸收”到超级项目中,该目录位于保存超级项目数据的.git下的目录中。


使用子模块和推入/提取

使用常规的Git存储库通常有点复杂,因为Git是分布式版本控制系统。这意味着您不仅需要管理您的存储库,还必须担心其他一些存储库,例如GitHub上的一个存储库,该存储库主要包含相同的提交,但具有自己的分支名称。

换句话说,要使用一个Git存储库,您实际上是在使用两个 Git存储库:您的另一个,以及位于origin的另一个。您的工作量增加了一倍(或者更糟糕,因为它们之间的协调松散)。

将子模块添加到组合中时,工作量会再次加倍(或更糟),因为子模块是一个Git存储库,因此, it 具有一个origin也是如此。因此,现在您正在使用四个 Git存储库。您和您的原籍是相互协调的。并且您必须与子模块存储库进行协调。但是,您的子模块存储库也与 origin协调。

由于您的超级项目存储库不断分离子模块中的HEAD,因此实际上在子模块中执行任何 都需要输入它,并将其HEAD重新附加到< em>其分支名称(或在合适的情况下创建一个新的分支名称),然后进行工作并进行新的提交。完成这些新的提交后,您可能希望通过超级项目来测试它们,也许是通过在超级项目中进行提交来进行的。如果它们无法解决问题,则可能需要撤消所有这些提交。

(您可以根据需要在超级项目和子模块存储库中进行未提交的更改。根据您的任务和要求,这可能会更容易。)

无论如何,一旦子模块提交存在且正确,您将要使用子模块中的git push将这些提交发送到其origin。您可以在更新超级项目以使用这些提交之前或之后执行此操作。请记住,如果您确实要先更新超级项目,那么在从超级项目git push之前,应确保先从子模块git push开始。原因是其他想要您的新超级项目提交的人也将需要您的新子模块提交。