如何在git存储库中创建一个git子模块的现有目录

Dor*_*har 30 git version-control git-submodules

我对git-submodules很困惑.

基本上我的问题是我不能让git明白这~/main-project/submodule是一个子模块.


我对git子模块有很好的经验:
在我的dotfiles存储库中我创建了.gitmodules文件,~/dotfiles-repo并添加了路径和URL.从那时起,如果我对子模块中的文件进行更改并运行git status,我会得到类似的结果:.vim/bundle/auto-complete (new commits) # in red

我创建了.gitmodules文件~/main-project但是:

  • 如果我更改~/main-project/submodule,甚至推的变化,我没有得到这样一个类似的反应<submodule> (new commits) # in red中运行时git status~/main-project.我只是得到了在这些目录中所做的更改
  • 当我点击github这些目录的文件夹链接时,它并没有指示我自己的存储库,但我留在同一个存储库中.

    1. 也许我错过了重点.子模块的主要特征是什么?
    2. 为什么git理解dotfiles repo中的子模块而不是我的其他repo中的子模块?
    3. 是因为我已经告诉git将文件添加~/main-project/submodule到索引中吗?

我读过这个问题导致我得到了这个答案,但我不确定是否需要git-subtree.我不想做那些可能难以改变的事情.

编辑:这个建议的重复解决方案也不起作用,我收到了一个错误Updates were rejected because the remote contains work that you do not have locally.似乎@GabLeRoux几乎告诉我要推<repo-A>送到网址<repo-B>.

Dor*_*har 28

解决方案非常简单.它是从这里提取的.

  1. git rm submodule-dir
    这将删除git在进入后跟踪的所有文件 submodule-dir
  2. rm -rf submoduledir
    这将删除可能已经留下的所有其他文件,submodule-dir因为git忽略了它们.
  3. 现在,我们必须提交才能从索引中删除文件:
    git commit
    提交后,我们清理了git遵循但未遵循的文件submodul-dir.现在是时候做了:
  4. git submodule add <remote-path-to-submodule>
    这将重新添加子模块,但作为一个真正的子模块.
  5. 此时,检查.gitmodules并查看子模块是否已成功添加可能是个好主意.在我的情况下,我已经有一个.gitmodules文件,所以我不得不修改它.

编辑

v2.12.0-rc0开始,在这次提交之后,我们收到了git submodule absorbgitdirs,这正是我在发布这个问题时所需要的.

这是文档声明此命令的作用:

如果子模块的git目录在子模块内,则将子模块的git目录移动到其superprojects $GIT_DIR/modules路径中,然后通过设置core.worktree并添加指向嵌入在git目录中的git目录的.git文件来连接git目录及其工作目录.superprojects git目录.

因此,不是像@DomQ和我自己在之前的答案中所建议的那样重新开始,而是可以添加运行以下内容:

  1. 如果没有索引中删除的子模块,子模块的URL加入.gitmodules.git/config
    git submodule add <url> <path>
  2. 移动子模块的$GIT_DIR目录(.git在常规库),以.git/modules/<path>
    git submodule absorbgitdirs <path>

  • 我会说,rm -rf submoduledir感觉很危险...我会做一个mv submoduledir submoduledir.backup,直到我看到其他命令都起作用为止。(是的,我有点偏执。) (3认同)
  • rm -rf 是一个 Linux 命令,在这个线程中没有任何地方暗示我们都使用 Linux,答案还应该包含等效的 Windows CMD 行,或者至少澄清它仅适用于 Linux (2认同)

San*_*war 9

这些解决方案似乎都不适合我,所以我想出了自己的解决方案:

  1. 确保一个新的 git repo 已经存在,它将保存新子模块的内容,例如,我们将使用“ git@github.com:/newemptyrepo

  2. 导航到您正在模块化的目录:

cd myproject/submodule-dir
Run Code Online (Sandbox Code Playgroud)
  1. 从父项的索引中删除要成为的子模块:
git rm -r --cached .
Run Code Online (Sandbox Code Playgroud)
  1. 在未来的子模块中初始化一个新的 git repo:
git init
Run Code Online (Sandbox Code Playgroud)
  1. 为未来的子模块设置原点并进行第一次提交:
git remote add origin git@github.com:/newemptyrepo
git add . && git commit && git push --set-upstream origin master
Run Code Online (Sandbox Code Playgroud)
  1. 现在您必须导航到父存储库的顶级路径:
cd .. && cd `git rev-parse --show-toplevel`
Run Code Online (Sandbox Code Playgroud)
  1. 最后,像往常一样添加子模块:
git submodule add git@github.com:/newemptyrepo ./myproject/submodule-dir
Run Code Online (Sandbox Code Playgroud)
  1. 现在提交并推送上述命令所做的更改,您就完成了!


Dom*_*omQ 6

基本上没有比假装重新开始更好的方法了

  1. 确保一切都在各处得到落实
  2. 将您的子存储库移开
  3. git submodule add从子存储库的远程
  4. cd mysubmodule
  5. git fetch ../wherever/you/stashed/the/sub-repository/in/step-1
  6. git merge FETCH_HEAD

为了解释为什么会这样,在我看来,需要更深入地了解子模块是什么git-submodule(1)而不是从手册页(甚至是Git 书中的相关章节)中收集到的内容。我在这篇博文中找到了一些更深入的解释,但由于该博文有点长,我冒昧在这里总结一下。

在较低级别上,git 子模块由以下元素组成:

  • 子模块树顶部的提交对象
  • .git/modules(在最新版本的 Git 中)用于托管子模块的 Git 对象的子目录,
  • 配置文件中的一个条目.gitmodules

提交对象包含(或更准确地说,由 SHA1 引用)在父树对象中。这是不寻常的,因为事情通常会以相反的方式发生,但这解释了为什么git status在子模块中执行提交后您会看到主存储库中出现一个目录。您还可以进行一些实验git ls-tree更详细地观察此提交对象。

in 中的子目录.git/modules代表.git子模块中的子目录;事实上,子模块中有一个.git 文件使用一行指向前者gitdir:这是自 Git 1.7.8 版本以来的默认行为。不知道为什么如果您继续拥有一个单独的.git目录,那么一切都不会正常工作,除非发行说明中指出,在具有子模块的分支和另一个不具有子模块的分支之间切换时,您可能会遇到麻烦。

该文件提供了朋友们应该从中获取的.gitmodulesURL ;git submodule update --remote这显然与主存储库的遥控器集不同。另请注意,该命令和在幕后调用它的其他命令.gitmodules部分复制到其中。.git/configgit submodule sync

虽然手动对.gitmodules+.git/config.git/modules+进行必要的更改相当容易mysubmodule/.git(事实上,甚至git submodule absorbgitdirs后者也可以),但实际上并没有一个瓷器可以只创建树内提交对象。因此,建议的解决方案是通过移动+重做上面提出的更改。


归档时间:

查看次数:

17881 次

最近记录:

7 年,8 月 前