Git——子目录中有Git项目时如何管理

Git——submodule

如果Git项目下面有个子项目也是Git下来(往往是git clone命令下载的)的,我们往往不能正常的提交和管理项目,本文给出了一些解决方案
如果子项目是git clone别人的项目,我们选择将子项目提交到整个大项目中
如果直接添加项目到Git往往提示:modified:xxx(modified content, untracked content)
此时如果直接提交,那么远程仓库里面子项目将是空的


融合子项目

删除.git/文件夹

  • 删除子项目下的.git/文件夹
    1
    rm -rf xxx/.git/

删除缓存

  • 删除之前提交过的子项目cache
    1
    2
    3
    4
    5
    # 删除子项目缓存 
    git rm -r --cached xxx/
    # 如果提示error: the following file has staged content different from both the file and the HEAD: xxx
    # 那么按照提示-f参数即可
    git rm -rf --cached xxx/

Note: 没有第二步的话直接进行第三步将和之前一样,子目录还是空的

重新添加

  • 重新添加子项目文件夹
    git add xxx

保持子项目为一个独立的项目

创建子项目

  • 像正常创建项目一样在Github上创建项目

  • 添加一个项目为子项目

    1
    git submodule add git@github.com:JoeZJH/Submodule.git submodule_name
    • 这个操作将会带来三方面的效果

      • 在当前文件夹和.git/modules/文件夹下以submodule_name为文件夹名创建新的文件夹
      • git@github.com:JoeZJH/Submodule.git链接和文件夹名submodule_name添加到当前文件夹的.gitmodules文件(若没有该文件则会自动新建该文件)和.git/config文件夹中
      • git@github.com:JoeZJH/Submodule.git项目中的文件下载到submodule_name中,并在submodule_name文件夹下生成.git文件夹
    • 需要注意的是:

      • 这里项目里面应该有内容(项目内容不能为空,否则添加会失败)
      • 理解:项目为空时被添加为子项目会在本地和.git/modules/中生成文件夹,但是不会执行后面的步骤
  • 查看添加项目结果

    1
    git status
    • 这里可以看到至少
      • .gitmodules被修改
      • submodule_name被添加
  • 提交子项目添加结果

    1
    2
    git add .
    git commit -m "comments"

修改子项目

  • 直接切换到子项目目录下
  • 然后按照正常Git项目操作,提交

在外层项目上提交子项目修改

  • 提交子项目修改直接把子项目的文件夹当成一个整体的文件
  • 子项目必须在全部修改内容被commit后才能被外层项目提交修改,否则在外层项目中执行git add .操作将无发添加子项目修改内容

移除子项目

  • 递归删除./.git/modules/下的子项目(模块)目录
  • 删除.gitmodules,.git/config中相关的模块条目

初始化带有子项目的项目

  • 正常拉取外层项目

    1
    git pull origin master:master
    • 此时关于子模块的信息除了./.gitmodules文件包含外,其他的文件都不包含,包括./.git
  • 初始化子模块

    1
    git submodule init
    • .gitmodules中的所有子模块注册到外层项目中
    • 注册方式: 添加子模块信息(文件夹路径和子模块项目地址)到.git/config文件中并指明子模块对应的active = true
  • 更新子模块(如果子模块之前存在于.git/config中,且active = false,这个初始化操作会修改为active = true)

    1
    git submodule update
    • .git/config.gitmodules中的所有子模块的链接地址项目下载到.git/modules/中,并自动同步(自动checkout操作)到子项目文件夹中
    • 注意git submodule init后,.git/config.gitmodules应该是一致的
    • .git/config.gitmodules中都有,且在.git/configactive = true的子项目才能被update操作下载

理解

  • 子项目自己知道自己被当做子项目
    • 一个项目被作为子项目后,他的./submodule_name/.git将不再是一个文件夹,而是一个指明.git/文件夹路径的配置文件
      1
      cat ./submodule_name/.git

gitdir: ../.git/modules/submodule_name

* `.git/`文件夹可以在`./.git/modules/submodule_name/.git/`中找到
  • 子项目相关信息都在外层项目中显示出来

  • 在子项目文件夹./submodule_name/下,子项目的更新,提交等操作正常按照一般项目进行即可

    • 这里操作时虽然仓库在外层项目的./.git/modules/submodule_name/.git/中,但是在子项目的目录下我们可以正常访问子项目的仓库
    • 也就是说在子项目文件夹下的git操作(add, commit)实际上不修改当前文件夹下的任何文件,修改都在外层项目的./.git/modules/submodule_name/.git/仓库中
  • 外层项目只存储

    • 子项目文件夹
    • ./.gitmodules中存储子项目相关信息(文件夹路径与子项目远程地址)
    • 在GitHub中,直接用网页打开项目可以看到子项目会被自动解析远程地址和最近提交的ID信息,点击子项目对应的文件夹链接即可跳转到子项目远程仓库地址中

递归子项目

  • 递归时记住项目的库都在副项目的库中即可
    • 这句话等价于所有项目的库都在根项目的.git/