将具有特定SHA1的子模块添加到现有git仓库

时间:2017-06-23 18:01:44

标签: git git-submodules

这些年来已被问过很多次,但从未见过真正的答案。

我想将一些开源代码作为子模块添加到现有项目中,但我只能使用特定的提交SHA1。

我已经设置了一个示例来演示这个问题。

所以,我的主要项目是:

https://github.com/BitvuLtd/myProj 

如您所见,此项目中有一个子模块指向:

https://github.com/BitvuLtd/strangersPro/tree/bd06980e0d711348bc7831f6421b3c5b27948781

我想指出下一行提交行:

https://github.com/BitvuLtd/strangersPro/tree/1463dd07645ce4e0450aabaa952b4c657d

我不想要最新的提交,因为它不兼容。

我最接近的是能够在子模块的单独克隆副本中检出正确的提交:

git checkout 1463dd07645ce4e0450aabaa952b4c657d16da39

但是如果我在主项目的子模块目录中这样做,它会得到:

fatal: reference is not a tree: 1463dd07645ce4e0450aabaa952b4c657d16da39

1 个答案:

答案 0 :(得分:1)

TL; DR:您需要更新您的gitlink

为此,您需要将子模块的Git存储库更新为所需的提交(提交,而不是树),然后在超级项目中运行git addgit commit

$ cd strangersPro
$ git checkout 1463dd07645ce4e0450aabaa952b4c657d16da39

然后返回超级项目并git add strangersPro并提交:

$ cd ..
$ git add strangersPro
$ git commit

详细信息

定义:子模块是一个Git存储库(不是一个非常有用的定义,但不完全是错误的)。术语“子模块”以几种不同的方式使用。通常“子模块”意味着“一个Git存储库被用作子模块”,这是一个可怕的定义,因为它有点begs the question,但不管怎么说,让我们继续使用它。 : - )

定义: superproject 是一个Git存储库,其中至少包含一个子模块。

定义: gitlink 是对另一个Git存储库的引用。这样的参考包括两个项目:

  • 我们将特定的其他Git存储库命名为
  • 的东西
  • 特定提交的哈希ID(我们假设)存在于其他Git存储库中。

您要做的是添加或更新gitlink

要将 new gitlink添加到Git存储库,以便此Git存储库成为包含子模块的超级项目,您必须在某个时刻(每个子模块只执行一次)运行git submodule add。这将创建或更新转换表。我们需要此表,因为存储在gitlink中的名称是路径名,例如strangersPro

此表的(文件)名称为.gitmodules,每个子模块包含多行。

在这个特殊情况下,已经完成了:有一个.gitmodules文件中包含这些行:

[submodule "strangersPro"]
    path = strangersPro
    url = https://github.com/BitvuLtd/strangersPro

现在我们有了这个包含此条目的文件,我们可以创建其中一个特殊的gitlink条目。 gitlink分为两部分。一个看起来像文件或目录/文件夹名称 - 在本例中为strangersPro。另一个是提交哈希ID。

路径名称strangersPro很容易看到。提交哈希ID不容易看到。但gitlink条目同时提供两者。同时,.gitmodules文件为您的Git提供了克隆单独的 Git存储库的方式,即子模块:.gitmodules文件表示要使用{{1}你的Git应该在strangersPro目录下克隆另一个存储库 - 子模块本身。

现在您的超级项目中有第二个Git存储库(在strangersPro中),您的超级项目的Git在子模块中运行另一个strangersPro。第二个git checkout使用gitlink中的提交哈希来检查一个特定的提交。

更新gitlink

现在你有了一个现有的gitlink,你的任务就变成了:更改哈希ID

您执行此操作的方式与更改存储库中的任何文件的方式相同:在运行git checkout后进行新提交。也就是说,gitlink 中检查每个提交,就像检查每个提交中的任何其他文件(如git add一样)。

但是,哈希ID只是大量无意义的数字,你不能直接编辑“gitlink文件”(它只保存在超级项目的索引/登台区域,而不是常规的工作树文件)。因此,要更新gitlink,您必须首先导航到子模块本身:

README.md

这个子模块本身就是一个Git存储库,就像任何其他Git存储库一样。这意味着您可以投放$ cd strangersPro git checkout以及git statusgit branch以及git add,依此类推。但是你想要做的就是检查一个新的特定提交。您将需要大量无意义的哈希ID。幸运的是,您提供了以上内容:它是git commit

1463dd07645ce4e0450aabaa952b4c657d16da39

现在你的子模块在这个提交时有一个分离的HEAD(而不是之前的旧的分离HEAD)。

现在您将子模块存储库的 out 导航回超级项目。您现在可以$ git checkout 1463dd07645ce4e0450aabaa952b4c657d16da39 子模块路径。您的超级项目git将从子模块中读取当前的提交哈希ID,并将其添加到您的超级项目的索引中:

git add

现在您已经准备好在超级项目中提交,在现有名称下记录新的哈希ID。