使用EXACT文件夹结构创建包含子模块的EXACT git存储库并将其推送到github

时间:2019-11-18 01:51:30

标签: git github git-submodules

我认为我的是git子模块最简单的用例。

我有一个目录结构

<project-name>
 ---<directory1>
 ---<directory2>
 ---<directory3>
        ---<directory3.1>

每个子目录都是一个git存储库。我只想跟踪添加到<project-name>目录中的不同git存储库,这是我的主要(或超级)存储库。

我已经弄清楚了如何将这些git存储库中的每一个作为子模块添加到我的超级存储库中,该超级存储库也是一个包含它们的目录。在本地,我正是想要的。

所以,只要我使用某些git子模块,它们就是我的超级存储库中的两个深度

git submodule add <relative-path-to-submodule> <relative-path-to-submodule>

可以很好地照顾它。

为什么我要这样做?因为这代表了CFD框架(OpenFOAM)中的常规本地目录结构,所以我正在为其开发代码。

我和其他人分别开发了不同的子模块,分别跟踪每个子模块/子目录绝对有价值。

目标是让最终用户克隆我的代码存储库,更改名称并开始编译和使用代码。 (按照惯例,构建起来非常容易)

我只是不知道如何将所有代码(包括来自
的实际文件)推送到github 子模块作为该特定子目录中的文件。

很显然,当我推送到github时,子模块只是显示为提交,因此没有实际的代码 子目录已推送。

我不想(负担不起)在超级仓库中添加子目录。所有答案都告诉我要这样做,这是没有意义的。

我找到了确切的问题,尚未解答(Git: Push a local git submodule, including submodule files, to a remote bare repository

5 个答案:

答案 0 :(得分:3)

  

我只是不知道如何将所有代码(包括来自子模块的实际文件,作为该特定子目录中的文件)推送到github。

首先,不要使用子模块,它们不适合您要执行的操作。

第二,尝试使用子树方法:我解释了between submodule and subtreeillustrated subtree here的区别。

请参阅:

  

git subtree使您可以将一个存储库作为子目录嵌套在另一个存储库中。这是Git项目可以管理项目依赖项的几种方法之一。

https://wac-cdn.atlassian.com/dam/jcr:f5fcef58-5b93-4ff4-b9a1-3f721d29ead8/BeforeAfterGitSubtreeDiagram.png?cdnVersion=685

答案 1 :(得分:1)

这是逐步进行复制的解决方案。这就是我使所有子模块工作流程正常工作的方式。

所涉及的最小示例存储库在此处链接为有兴趣的人:

https://github.com/jankapunkt/submodule-main

https://github.com/jankapunkt/submodules-sub1


第一部分-添加子模块

  1. 创建一个新的裸仓库,这将是我们的主要开发仓库。我们称之为ist yourName/submodule-main

  2. 创建第二个新存储库,其中包含一些文件夹和内容,这将是我们的子模块存储库。我们称之为yourName/submodules-sub1

  3. 克隆sub1存储库,添加一些内容并将其推回到origin

git clone git@github:yourName/submodules-sub1.git
cd submodules-sub1/

# create some content
mkdir somefolder
touch HELLO.md
echo "yeehaw" > ./HELLO.md

# add, commit and push
git add somefolder/
git commit somefolder/HELLO.md -m "added some content"
git push origin master
# note the commit hash here: 
# dbcc1ef..8293526  master -> master
  1. 返回并删除存储库(或没有关系,没关系)

  2. 克隆submodule-main存储库

cd ..
git clone git@github.com:yourName/submodule-main.git
  1. 添加sub1作为子模块,并跟踪特定分支(在本例中为master分支):
cd ./submodule-main/
git submodule add -b master git@github.com:jankapunkt/submodules-sub1.git ./submodules-sub1

请注意,模式为submodule add -b <branch> <repository> <path>。现在创建的结构如下所示:

.
..
.git
.gitmodules
LICENSE
README.md
submodules-sub1

并且.gitmodules应该包含

[submodule "submodules-sub1"]
    path = submodules-sub1
    url = git@github.yourName/submodules-sub1.git
    branch = master
  1. 添加/提交这些更改
git add -A
git commit -a -m "sub1 submodule added"
git push origin master

在Github上检查您的存储库,它将包含sub1当前开发状态​​的精确副本,包括对最新提交的引用,例如:

submodules-sub1 @ 8293526

它应该包含此子模块的引用提交的完整副本/快照,包括所有文件和文件夹。

第二部分-更新子模块

现在,您想始终以子仓库的跟踪状态更新主仓库。

  1. 进入子模块目录并进行一些更改
cd submodules-sub1/somefolder/
touch FOO.md
echo "bar baz" > FOO.md
git add FOO.md
git commit FOO.md -m "added FOO.md"
  1. 将您的状态推送到分支,submodule-main存储库将跟踪该分支

现在有两种情况可能发生。输入git status以查看您当前的HEAD职位:

a-您已经在跟踪主人

On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

太好了,您已经在跟踪正确的分支,仅git push origin master

b-您处于分离的HEAD状态(例如,submodule-main做过submodules update之后)

现在您需要使HEAD指向正确的提交(我在这里使用一些示例哈希):

git log -1 # copy the commit hash, for example e6227de6b7042c06afa0062ec900386a817a058e
git checkout master
git reset --hard e6227de6b7042c06afa0062ec900386a817a058e
git push origin master
  1. 更新主仓库

现在,您已经更新了sub1目录中的代码,但是main中尚未更新任何代码。因此,我们还需要更新main存储库并指向最新的子模块提交:

cd ..
git status

您应该看到有关新提交的通知:

Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   submodules-sub1 (new commits)

no changes added to commit (use "git add" and/or "git commit -a")

现在您也要提交这些更改,并将所有更改推送到您的origin

git commit submodules-sub1/ -m "sub1 updated some folder content"
git push origin master

请注意,在您的origin存储库中没有指向另一个提交:

main

第三部分-克隆最终用户

假设您的最终用户现在想要克隆一种“快照”,其中所有子模块都指向某个分支上的某个提交(我在这里使用最新提交的submodules-sub1 @ e6227de 对此进行了简化),他们应该克隆递归并应该能够立即构建:

master

您还可以通过输入git clone git@github.com:jankapunkt/submodule-main.git --recurse-submodules 文件夹并输入submodules-sub1来验证这一点,该文件夹现在应指向git status

e6227de

使用的文档是

https://git-scm.com/docs/git-submodule

https://git-scm.com/docs/git-clone

答案 2 :(得分:1)

尝试使用git subtree代替git submodule

听起来子模块不是执行您要执行的操作的最佳方法。我建议改用子树。子树类似于子模块,但是有一些差异,这些差异在您的用例中会更好。

以下是git subtree的工作方式的恰当解释:

https://www.atlassian.com/git/tutorials/git-subtree

简而言之,子树类似于子模块,它们允许您将一个存储库添加为另一个存储库的子目录,可以选择跟踪远程引用和提交历史记录。

使用子树时,包含的存储库中的所有源代码都将包含在您自己的存储库中。所有人都需要做的事情就是克隆您存储库中的所有代码,而随附的存储库就是克隆您的存储库。无需其他设置步骤。

子树还可以轻松地修改所包含的存储库的代码,并将更改推回原始存储库。

这是添加子模块的示例命令:

git subtree add --prefix <subdir> <other repo> <branch of other repo>

您不能对子模块做您想做的事

Git子模块不会在git存储库中存储其他存储库的代码。相反,它们将对另一个存储库的引用存储在.gitmodules文件中。您将能够在存储库中看到.gitmodules文件。使用子模块时,这是子存储库中子存储库存在的唯一容量。该代码不在您的存储库中。

https://git-scm.com/book/en/v2/Git-Tools-Submodules

  

DbConnector目录在那里,但是为空。您必须运行两个命令:git子模块init初始化本地配置文件,以及git子模块更新以从该项目中获取所有数据并检出超级项目中列出的适当提交

答案 3 :(得分:0)

  

子模块允许您将Git存储库保留为另一个Git存储库的子目录。这使您可以将另一个存储库克隆到项目中,并将提交分开保存。-git-scm.com

因此,您想要做的是反对git中的子模块设计。当您想将文件跟踪到您的仓库中时,这意味着您希望将提交放在一起。但是,根据您的目标。您无需将确切的文件夹推送到“主”存储库中。

添加子模块时,将创建文件.gitmodules并跟踪此当前存储库中所需的其他源。该文件将被推送到您的存储库中(例如,与.gitignore相同),并且在有人克隆该文件时,只需使用命令:git clone --recurse-submodules https://github.com/chaconinc/MainProject,它将不仅获取您的代码,还获取以下代码: .gitsubmodules文件中跟踪的每个子模块。

参考:https://git-scm.com/book/en/v2/Git-Tools-Submodules

答案 4 :(得分:0)

  

我只是不知道如何将所有代码(包括来自子模块的实际文件,作为该特定子目录中的文件)推送到github。

您肯定知道:超级存储库只能通过其 commits 来“查看”子模块的内容。
这意味着您必须分别提交所有子模块,然后才能提交超级存储库的合并版本:

cd directory1
git add <files...>
git commit
git push    # if you want to *share* the content with others, you additionally need to 
            # publish the content of this subrepo (aka : git push)
cd ..

cd directory2
git add <files...>
git commit
git push
cd ..

# etc ...
# and finally, from root folder :
git add *
git commit
git push

请注意,相同的规则适用于directory3
如果directory3.1directory3的子模块,则需要在提交directory3.1之前提交directory3的内容。

您可以编写一个脚本,该脚本将扫描每个子模块并运行所述操作,这可以减少要做的文书工作量,但是需要应用这些操作。


如果您希望能够将根存储库更像具有常规存储库(而不是子模块)的“您看到的文件”来处理,我将第二次VonC's advice:看看如何使用{{1} }。

它确实带有自己的额外任务列表(用于更新,推送到子存储库,合并...),
但是它还使您可以查看和提交主存储库的文件,而不必强制遵循模块层次结构。