Git-将单独的存储库映射到源代码树中的子目录

Git-将单独的存储库映射到源代码树中的子目录,git,Git,TL;DR version-我希望跟踪独立存储库中多个独立应用程序的活动开发,但所有这些应用程序都显示为使用不同名称在单个源代码树下进行管理,如下所示: /root --> REPO_1 /app1 --> REPO_2 /app2 --> REPO_3 /lib --> REPO_4 /build

TL;DR version-我希望跟踪独立存储库中多个独立应用程序的活动开发,但所有这些应用程序都显示为使用不同名称在单个源代码树下进行管理,如下所示:

/root                      --> REPO_1
  /app1                    --> REPO_2
  /app2                    --> REPO_3
  /lib                     --> REPO_4
/build
  /app1dir
    Makefile
  /app2dir
    Makefile
  /lib
    /Makefile
    /lib1
      /Makefile
    /lib2
      /Makefile
我尝试了git子模块,但因为它们与特定的提交绑定,所以它们不能完成我需要它们做的事情。只需将存储库克隆到一个子目录,我们的架构师(他随后建议使用子模块)就反对这一做法。有没有其他选择可以满足我的需求

Peter Jackson LotR Extended Blu-Ray version:我们正在从CVS迁移到Git,这是自动化代码构建和部署的更大努力的一部分,我陷入了需要一些指导的境地

我们有40多个不同的应用程序,它们都属于同一个范畴,组织方式如下:

/root_src_dir
  /app1dir
    /Makefile.in
    /src1.cpp
    /src2.cpp
    ...
  /app2dir
    /Makefile.in
    /src1.cpp
    /src2.cpp
    ...
  configure.in
  /lib
    /Makefile.in
    /lib1
      /Makefile.in
      /src.cpp
      ...
    /lib2
      /Makefile.in
      /src.cpp
      ...
  Makefile.in
lib
子目录包含所有不同应用程序使用的公共库代码。否则,应用程序不会共享代码。它们在很大程度上相互独立。它们彼此独立部署,库代码作为
文件独立部署。一个的提交历史不应影响另一个的提交历史

为了构建,我们在
根目录下的
configure.in
文件中运行
autoconf
;然后,我们在与
root\u src\u dir
相同的级别上创建一个
build
目录,并从那里运行生成的
configure
脚本。然后,
configure
脚本创建构建目录树,并在该树中生成适当的makefile

简而言之,从
build
目录运行
root\u src\u dir/configure
后,我们得到以下结果:

/root                      --> REPO_1
  /app1                    --> REPO_2
  /app2                    --> REPO_3
  /lib                     --> REPO_4
/build
  /app1dir
    Makefile
  /app2dir
    Makefile
  /lib
    /Makefile
    /lib1
      /Makefile
    /lib2
      /Makefile
库子目录的Makefile在
build
下创建一个
includes
子目录,并将所有库文件头复制到该子目录

在当前CVS配置下,所有内容都集中在
根目录下的单个存储库中

作为迁移的一部分,我希望将每个应用程序移动到其自己的单独存储库中,原因如下:

  • 这些应用程序在很大程度上相互独立;他们共享的唯一代码是公共库代码(将保存在其单独的存储库中)
  • 自动配置管理工具(我们不拥有)假定每个应用程序都保存在单独的存储库中
  • 构建整个世界需要一段时间,不需要部署单个应用程序更新
  • 我希望能够跟踪每个应用程序的版本,并将它们保存在单独的存储库中,这样做会更容易
  • 但是,我希望保持现在使用的相同目录结构,因为:

  • 我不想通过几十个异常神秘的makefile来改变路径和依赖关系
  • 我不想为我们的开发人员显著改变流程
  • 我希望在开发中保持相同的命名约定(auto CM工具使用了一种……麻烦的……命名约定)
  • 所以,我做了一些实验。现在我有这样的事情:

    /STUPID_ACM_NAMING_CONVENTION_ROOT_DIR
      /configure.in
      /Makefile.in
    /STUPID_ACM_NAMING_CONVENTION_APP1
      /Makefile.in
      /src.cpp
      ...
    /STUPID_ACM_NAMING_CONVENTION_APP2
      /Makefile.in
      /src.cpp
      ...
    /STUPID_ACM_NAMING_CONVENTION_LIB
      /Makefile.in
      /lib1
        /Makefile.in
        /src.cpp
        ...
      /lib2
        /Makefile.in
        /src.cpp
    
    作为第一步,我将
    dumby\u ACM\u NAMING\u CONVENTION\u ROOT\u DIR
    克隆到名为
    ROOT\u src\u DIR
    的目录中,然后在
    ROOT\u src\u DIR
    下,我使用旧的命名约定将每个应用程序存储库克隆到一个子目录中:

    $ git clone $REPO_HOME/STUPID_ACM_NAMING_CONVENTION_ROOT_DIR root_src_dir
    $ git clone $REPO_HOME/STUPID_ACM_NAMING_CONVENTION_APP1 root_src_dir/app1dir
    $ git clone $REPO_HOME/STUPID_ACM_NAMING_CONVENCTION_APP2 root_src_dir/app2dir
    $ git clone $REPO_HOME/STUPID_ACM_NAMING_CONVENTION_LIB root_src_dir/lib
    
    这“奏效”;我能够以我一贯的方式建造房屋;更好的是,我编写了一个脚本,只需克隆根目录、库目录和应用程序目录即可进行构建(无需复制整个源代码树即可构建单个应用程序)。我可以在自己的存储库中跟踪每个应用程序,并以有意义的方式对其进行标记。推和拉似乎很有效,并没有在分支和合并方面发挥太多的作用,但我们无论如何也不会对其产生幻想。然而,我被告知这不是一个最佳的解决方案,因为CM小组不知道我们的目录结构,所以如果没有我们的输入(或脚本),他们将无法复制这个

    很公平。所以我玩了子模块。我看过很多关于“网络警告子模块”的文章,现在我明白了原因。将子模块附加到父项目时,即附加了特定的提交;您可以更新应用程序存储库,但克隆父项目时,这些更改不会反映在子模块中。看起来子模块非常适合跟踪变化不大的外部依赖项,但不适合跟踪活动开发


    因此,克隆到子目录是不可能的(架构师不喜欢),子模块是不可能的(不做我需要的)。我还有其他选择吗?我如何才能获得为每个应用程序使用单独的repo的好处,同时最大限度地减少对当前构建过程(假定特定的目录结构)的影响?我们是一个小组(大约6个开发人员),代码中没有太多的搅动,我们通常不重叠开发,我们不需要一堆不同的特性分支

    您可以使用子模块来实现这一点。您能否澄清子模块没有做您希望他们做的事情的确切原因?我认为你对子模块有一些错误的假设,通过说明子模块不做什么,这些假设就会变得清晰起来。@PeterTillemans:我在子模块中工作;我将更改推送到相应的存储库。然后,我将超级项目克隆到其他地方进行构建。我的更改没有显示在克隆项目中。重新阅读子模块,看看我做错了什么。@JohnBode提交/推送顶级项目时,您的更改将显示出来。更改子模块的sha-1将在tople中更新