基本上我的问题是我不能让git明白~/main-project/submodule
是一个子模块。
我对git子模块有很好的经验:
在我的dotfiles repository中,我在~/dotfiles-repo
中创建了.gitmodules文件,并添加了路径和网址。从那时起,如果我对子模块中的文件进行更改并运行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
,它并没有将我引导到存储库本身,而是保留在同一个存储库中。
~/main-project/submodule
内的文件添加到索引中?我已阅读this question,这导致我this answer但我不确定是否需要git-subtree
。我不想做那些可能难以改变的事情。
修改:This suggested duplicate-solution也没有用,我收到
Updates were rejected because the remote contains work that you do not have locally
的错误。似乎@GabLeRoux实际告诉我将<repo-A>
推送到<repo-B>
的网址。
答案 0 :(得分:25)
解决方案非常简单。它是从here中提取的。
git rm submodule-dir
submodule-dir
rm -rf submoduledir
submodule-dir
中可能遗留的所有其他文件,因为git忽略了它们。git commit
submodul-dir
中跟踪。
现在是时候了:git submodule add <remote-path-to-submodule>
.gitmodules
并查看子模块是否已成功添加可能是个好主意。在我的情况下,我已经有一个.gitmodules
文件,所以我不得不修改它。自v2.12.0-rc0以来this commit之后,我们收到了git submodule absorbgitdirs
,这正是我在发布此问题时所需要的。
这是此命令执行的docs状态:
如果子模块的git目录在子模块中, 将子模块的git目录移动到其超级项目中
$GIT_DIR/modules
路径,然后连接git目录和 它的工作目录是设置core.worktree
并添加 一个.git文件,指向嵌入在中的git目录 superprojects git目录。
所以不要像@DomQ和我之前的答案中所建议的那样重新开始,而是可以添加运行以下内容:
.gitmodules
并添加到.git/config
git submodule add <url> <path>
$GIT_DIR
目录(常规存储库中的.git
)移动到.git/modules/<path>
git submodule absorbgitdirs <path>
答案 1 :(得分:3)
基本上没有比假装重新开始更好的方式:
git submodule add
来自子存储库的远程cd mysubmodule
git fetch ../wherever/you/stashed/the/sub-repository/in/step-1
git merge FETCH_HEAD
为了解释为什么会出现这种情况,在我看来,除了可以从git-submodule(1)
手册页(或者甚至是relevant chapter from the Git book)。我在this blog post找到了一些更深入的解释,但由于这篇文章有点冗长,我在这里总结一下。
在较低级别,git子模块由以下元素组成,
.git/modules
中的一个子目录,用于托管子模块的Git对象,.gitmodules
配置文件中的条目。在父树对象中包含(或更确切地说,由SHA1引用)提交对象。这是不寻常的,因为事件usually反过来发生了,但这解释了为什么在子模块中执行提交后,您会看到主存储库git status
中出现一个目录。您还可以使用git ls-tree
使some experiments更详细地观察此提交对象。
.git/modules
中的子目录代表子模块中的.git
子目录;实际上,子模块中有一个.git
文件,它使用gitdir:
行指向前者。这是默认行为since version 1.7.8 of Git。如果你只是继续使用一个单独的.git
目录,不确定为什么一切都不会正常工作,除非在发行说明中注明,在具有子模块的分支和另一个分支之间切换时可能会遇到麻烦那不是。
.gitmodules
文件提供git submodule update --remote
和朋友应该从中提取的网址;这显然不同于主存储库的一组遥控器。另请注意,.gitmodules
被.git/config
命令以及在幕后调用它的其他命令部分复制到git submodule sync
。
尽管对.gitmodules
+ .git/config
以及.git/modules
+ mysubmodule/.git
进行必要的更改非常容易(事实上,甚至还有对于后者,git submodule absorbgitdirs
,实际上并不是仅仅创建树内提交对象的瓷器。因此,通过上述移动+重做更改提出了解决方案。
答案 2 :(得分:2)
这些解决方案似乎都不适合我,所以我想出了自己的方法:
确保已存在一个新的git repo来保存内容 例如,我们将使用“ git@github.com:/ newemptyrepo ”
导航到您要调制的目录:
cd myproject/submodule-dir
git rm -r --cached .
git init
git remote add origin git@github.com:/newemptyrepo
git add . && git commit && git push --set-upstream origin master
cd .. && cd `git rev-parse --show-toplevel`
git submodule add git@github.com:/newemptyrepo ./myproject/submodule-dir
答案 3 :(得分:1)
按顺序回答您的问题:
git rm --cached submodule-name/
。然后创建一个中间提交,然后添加文件夹作为存储库:git add submodule-name
(注意在子模块名称后面有没有尾部斜杠子模块的情况)。您提到的answer也可以更正您提交的历史记录:
该文件夹将被视为所有提交历史记录中的子模块,而不仅仅是所有未来的提交。如果您签出以前版本,它被视为文件夹,这可以避免任何复杂情况。这是一个复杂的问题,因为当您返回到分支的提示时,您可能还必须输入您的子模块并签出到最新的提交以恢复所有文件(可能从您的工作目录中删除)。这可以通过对您的最新提交进行某种递归检查来避免。
如果修改了提交历史记录,那么所有其他贡献者也必须重新克隆项目,因为它们会发生合并冲突或更糟;重新引入问题会提交回项目。