使用git子模块管理项目

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用git子模块管理项目相关的知识,希望对你有一定的参考价值。

使用git子模块管理项目

简介

开发过程中,往往需要将将项目拆分成不同的模块,Git子模块(git submodule)可以协助我们高效地进行项目管理。另外,子模块的思想也能够强化模块间的独立性,显著降低模块间的耦合度。

参考链接

官方文档:https://git-scm.com/book/zh/v2/Git-工具-子模块

《Pro Git》的 子模块章节,https://www.ycmbcd.com/doc/progit/

子模块的基本使用

创建主模块

  • github上创建主模块工程,克隆到本地
    jun@jun:~/work/github$ git clone git@github.com:embedded-jun/main-module.git
    

创建子模块

  • github上创建子模块工程

加入子模块

  • git submodule add参数

    git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
    
  • 将子模块加入到主模块,加入主模块时如果不指定路径,默认就是当前目录

    jun@jun:~/work/github$ cd main-module/
    jun@jun:~/work/github/main-module$ git submodule add git@github.com:embedded-jun/sub-module1.git
    
  • 查看子模块

  • git submodule查看子模块, 可以看到当前追踪的子模块 commit id

    jun@jun:~/work/github/main-module$ git submodule
     5b30473ad657858aa43662b7acdd69538eb3b0f5 sub-module1 (heads/main)
    
  • 查看 .gitmodules文件,该文件中说明了子模块的 相对路径以及 url

    jun@jun:~/work/github/main-module$ cat .gitmodules
    [submodule "sub-module1"]
            path = sub-module1
            url = git@github.com:embedded-jun/sub-module1.git
    
  • 查看 .git/modules文件,该目录保存了子模块的一些相关信息

    jun@jun:~/work/github/main-module$ ls .git/modules/
    sub-module1
    jun@jun:~/work/github/main-module$ ls .git/modules/sub-module1/
    branches  config  description  HEAD  hooks  index  info  logs  objects  packed-refs  refs
    
  • 使用 git status查看

    jun@jun:~/work/github/main-module$ git status
    On branch main
    Your branch is up to date with \'origin/main\'.
    
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
          new file:   .gitmodules
          new file:   sub-module1
    
  • 此时子模块还没有真正加入到主模块中,如果执行 git submodule deinit删除子模块时会报错,必须commit一次,才算真正加入了子模块

    jun@jun:~/work/github/main-module$ git commit -m "feat: add submodule sub-module1"
    [main 0089fb8] feat: add submodule sub-module1
    2 files changed, 4 insertions(+)
    create mode 100644 .gitmodules
    create mode 160000 sub-module1
    

删除子模块

  • git submodule deinit参数
    git submodule [--quiet] deinit [-f|--force] (--all| [--] <path>...)
    
  • 删除
    jun@jun:~/work/github/main-module$ git submodule deinit ./sub-module1/
    Cleared directory \'sub-module1\'
    Submodule \'sub-module1\' (git@github.com:embedded-jun/sub-module1.git) unregistered for path \'sub-module1\'
    jun@jun:~/work/github/main-module$ git rm ./sub-module1/
    rm \'sub-module1\'
    
  • git status查看
    jun@jun:~/work/github/main-module$ git status
    On branch main
    Your branch is ahead of \'origin/main\' by 1 commit.
    (use "git push" to publish your local commits)
    
    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
          modified:   .gitmodules
          deleted:    sub-module1
    
  • 查看 .gitmodules文件的变化,可以看到子模块相关信息已经被删除了
    jun@jun:~/work/github/main-module$ git diff --cached .gitmodules
    diff --git a/.gitmodules b/.gitmodules
    index 8961d31..e69de29 100644
    --- a/.gitmodules
    +++ b/.gitmodules
    @@ -1,3 +0,0 @@
    [submodule "sub-module1"]
         path = sub-module1
         url = git@github.com:embedded-jun/sub-module1.git
    
  • 做一次提交
    jun@jun:~/work/github/main-module$ git commit -m "feat: delete submodule sub-module1"
    [main 8499fe4] feat: delete submodule sub-module1
    2 files changed, 4 deletions(-)
    delete mode 160000 sub-module1
    

更新子模块

  • 在子模块中创建并提交文件main.cpp

    jun@jun:~/work/github/main-module/sub-module1$ git status
    On branch main
    Your branch is up to date with \'origin/main\'.
    
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
          main.cpp
    
    nothing added to commit but untracked files present (use "git add" to track)
    jun@jun:~/work/github/main-module/sub-module1$ git add .
    jun@jun:~/work/github/main-module/sub-module1$ git commit -m "feat:add main.cpp"
    [main 8332956] feat:add main.cpp
    1 file changed, 6 insertions(+)
    create mode 100644 main.cpp
    
  • 在父目录即主模块中使用git status查看状态,可见主模块并不知道子模块中哪些文件做了修改,只知道子模块有变化

    jun@jun:~/work/github/main-module$ git status
    On branch main
    Your branch is up to date with \'origin/main\'.
    
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
          modified:   sub-module1 (new commits)
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
  • 在主模块中使用git diff查看有哪些变化,可见只有.gitmodules中子模块的commit id发生了变化

    jun@jun:~/work/github/main-module$ git diff
    diff --git a/sub-module1 b/sub-module1
    index 5b30473..8332956 160000
    --- a/sub-module1
    +++ b/sub-module1
    @@ -1 +1 @@
    -Subproject commit 5b30473ad657858aa43662b7acdd69538eb3b0f5
    +Subproject commit 8332956869efb53b6952c9bdbb687317f78362ac
    

  • 在主模块中更新子模块的commit id

克隆含有子模块的项目

git clone git@github.com:embedded-jun/main-module.git --recursive

致谢

感谢大佬鹏哥近三年来的指导,恭喜鹏哥更进一步!
莫问前程事,飒然沙上蓬
他日见张禄,绨袍怀旧恩

git基础教程(36)submodule 子模块的管理和使用

文章目录

1、使用前提

经常碰到这种情况:当你在一个Git 项目上工作时,你需要在其中使用另外一个Git 项目。也许它是一个第三方开发的Git 库或者是你独立开发和并在多个父项目中使用的。这个情况下一个常见的问题产生了:你想将两个项目单独处理但是又需要在其中一个中使用另外一个。

在Git 中你可以用子模块submodule来管理这些项目,submodule允许你将一个Git 仓库当作另外一个Git 仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持你的提交相对独立。

2、添加子模块

此文中统一将远程项目https://github.com/maonx/vimwiki-assets.git克隆到本地assets文件夹。

$ git submodule add https://github.com/maonx/vimwiki-assets.git assets

添加子模块后运行git status, 可以看到目录有增加1个文件.gitmodules, 这个文件用来保存子模块的信息。

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   .gitmodules
    new file:   assets

3、查看子模块

$ git submodule
 e33f854d3f51f5ebd771a68da05ad0371a3c0570 assets (heads/master)

4、更新子模块

  • 更新项目内子模块到父模块期望的版本

    $ git submodule update
    
  • 更新子模块为远程项目的最新版本

    $ git submodule update --remote
    

5、克隆包含子模块的项目

克隆包含子模块的项目有二种方法:一种是先克隆父项目,再更新子模块;另一种是直接递归克隆整个项目。

6、克隆父项目,再更新子模块

  1. 克隆父项目
$ git clone https://github.com/maonx/vimwiki-assets.git assets
  1. 查看子模块
$ git submodule
 -e33f854d3f51f5ebd771a68da05ad0371a3c0570 assets

子模块前面有一个-,说明子模块文件还未检入(空文件夹)。

  1. 初始化子模块
$ git submodule init
Submodule 'assets' (https://github.com/maonx/vimwiki-assets.git) registered for path 'assets'

初始化模块只需在克隆父项目后运行一次。

初始化的动作实际上是从.gitsubmodule文件中读取submodule信息写到文件.git/config:

  6 [remote "origin"]
  7         url = https://github.com/grpc/grpc.git
  8         fetch = +refs/heads/*:refs/remotes/origin/*
  9 [branch "master"]
 10         remote = origin
 11         merge = refs/heads/master
 12 [submodule "third_party/abseil-cpp"]
 13         url = https://github.com/abseil/abseil-cpp.git
 14 [submodule "third_party/benchmark"]
 15         url = https://github.com/google/benchmark
 16 [submodule "third_party/bloaty"]
  1. 更新子模块
$ git submodule update
Cloning into 'assets'...
remote: Counting objects: 151, done.
remote: Compressing objects: 100% (80/80), done.
remote: Total 151 (delta 18), reused 0 (delta 0), pack-reused 70
Receiving objects: 100% (151/151), 1.34 MiB | 569.00 KiB/s, done.
Resolving deltas: 100% (36/36), done.
Checking connectivity... done.
Submodule path 'assets': checked out 'e33f854d3f51f5ebd771a68da05ad0371a3c0570'

7、递归克隆整个项目

git clone https://github.com/maonx/vimwiki-assets.git assets --recursive 

递归克隆整个项目,子模块已经同时更新了,一步到位。

8、修改子模块

在子模块中修改文件后,直接提交到远程项目分支。

$ git add .
$ git ci -m "commit"
$ git push origin HEAD:master

9、删除子模块

删除子模块比较麻烦,需要手动删除相关的文件,否则在添加子模块时有可能出现错误
同样以删除assets文件夹为例

  1. 删除子模块文件夹
$ git rm --cached assets
$ rm -rf assets
  1. 删除.gitmodules文件中相关子模块信息
[submodule "assets"]
  path = assets
  url = https://github.com/maonx/vimwiki-assets.git
  1. 删除.git/config中的相关子模块信息
[submodule "assets"]
  url = https://github.com/maonx/vimwiki-assets.git
  1. 删除.git文件夹中的相关子模块文件
$ rm -rf .git/modules/assets

以上是关于使用git子模块管理项目的主要内容,如果未能解决你的问题,请参考以下文章

Git Submodule管理项目子模块

Git Submodule管理项目子模块

Git Submodule管理项目子模块

Git Submodule管理项目子模块

Git Submodule管理项目子模块

Git子模块与依赖管理?