Git Submodule管理项目子模块的使用_其它综合

来源:脚本之家  责任编辑:小易  

对于一个较2113大的Git工程,你可能会想5261在多个仓库之间共享4102代码,不管这些代码是在多个不同产品间1653使用的项目共享库或是一些模板。Git通过子模块来实现这样的需求。子模块允许将其他代码仓库的克隆作为子目录放到一个父仓库(有时候也称为父项目)中。一个子模块也是一个独立的仓库,你可以像其他仓库一样执行commit,branch,rebase等等操作。JGit提供了实现大部分Git子模块命令的API。我将在这儿给大家介绍这些API。设置本文中用到的代码片段将作为学习测试程序。简单的测试程序有助于理解第三方库是如何工作,以及如何使用新的API。你可以将这些测试程序看做是可控制的试验,帮助你更加直观地发现第三方代码是如何执行的。除此之外,如果你保持编写测试程序,可以帮助你检验第三方代码的新版本。如果你的测试程序涵盖了如何调用这些库,那么第三方代码中不兼容的修改将会尽早展现出来。回到之前的话题,所有的测试程序共享同一个设置,详细信息请查看源代码。现在有一个空的仓库,叫parent,以及另一个仓库叫library。测试程序中,library将会作为子模块添加到parent仓库中。library仓库初始化提交了一个readme.txt文件。测试程序中有一个setUp方法,用来创建这两个仓库,如下所示:1 Git git = Git.init().setDirectory( "/tmp/path/to/repo" ).call();这两个仓库用类型为Git的parent和library变量表示。该类封装了一个仓库并允许访问JGit的所有可用指令。就如较早之前我在这里中提到,每个Commnad类对应于一条原生的Git pocelain指令。调用一个指令需要用到生成器模式。举个例子,执行Git.commit()的结果实际上相当于一个CommitCommand。你可以提供一些必要的参数去调用它的call()方法,从而执行相应的指令。添加一个子模块第一步当然是在一个已有的仓库添加子模块。通过上面提到的setUp步骤,library仓库应当作为子模块添加到parent仓库的modules/library目录下。12345678910111213141516 @Testpublic void testAddSubmodule() throws Exception { String uri = library.getRepository().getDirectory().getCanonicalPath(); SubmoduleAddCommand addCommand = parent.submoduleAdd(); addCommand.setURI( uri ); addCommand.setPath( "modules/library" ); Repository repository = addCommand.call(); repository.close(); F‌ile workDir = parent.getRepository().getWorkTree(); F‌ile readme = new F‌ile( workDir, "modules/library/readme.txt" ); F‌ile gitmodules = new F‌ile( workDir, ".gitmodules" ); assertTrue( readme.isF‌ile() ); assertTrue( gitmodules.isF‌ile() );}SubmoduleAddCommand对象需要知道两件事,第一是子模块从哪里克隆而来,第二是它应该存放在哪里。URI属性表示仓库库的克隆地址,这个克隆地址将会传递给clone命令。path属性则指定了相对于parent仓库根工作目录的路径,子模块将被存放在这个路径。这个指令执行之后,parent仓库的工作目录将会变成这样:library仓库存放在modules/library目录下,而且它的工作目录树被检出。call()方法返回一个Repository对象,你可以把它当做一个常规的仓库来使用。这也意味着,你必须在程序中明确显式地关闭返回的仓库,以避免文件句柄泄露。从上图我们可以看到,SubmoduleAddCommand做了一件事,它在parent仓库的根工作目录下创建了一个.git模块文件,并把它添加到索引中。123 [submodule "modules/library"]path = modules/libraryurl = git@example.com:path/to/lib.git如果你打开过Git的配置文件,你会发现以上句法。这个文件列出了当前仓库的所有子模块。对于每个模块,文件中列出了它仓库URL地址以及本地路径。一旦commit并push了这个文件,克隆这个仓库的一方就知道哪里可以获取相应的子模块(稍后会详细讲解)。列出子模块当我们添加了一个子模块之后,我们可以会想知道,它是否对于父仓库来说是可知的。第一项测试中我们做了一个基础的检测,验证了某些文件和目录的存在。我们也可以使用一个API来列出一个仓库的子模块,如下所示:1234567891011 @Testpublic void testListSubmodules() throws Exception { addLibrarySubmodule(); Map<String,SubmoduleStatus> submodules = parent.submoduleStatus().call(); assertEquals( 1, submodules.size() ); SubmoduleStatus status = submodules.get( "modules/library" ); assertEquals( INITIALIZED, status.getType() );}SubmoduleStatus命令返回了一个子模块的Map集合,其中键是子模块的路径,值是这个模块的状态值。通过以上代码我们能够验证子模块确实已经添加进去,而且它的状态是INITIALIZED的。这个命令还允许添加一个或多个路径来限制子模块状态。说到状态,JGit的StatusCommand并非原生的Git指令。如果在执行指令时添加选项‐‐ignore-submodules=dirty,那么所有对子模块工作目录的修改都会被忽略。更新子模块子模块通常指向他们所在的仓库的一次特殊的提交。如果之后有人克隆了父仓库,他们也会获得与之完全相同的子模块状态,即便子模块的上游有新的提交。为了修改子模块,你像一下代码一样明确地对其进行更新:1234567891011121314 @Testpublic void testUpdateSubmodule() throws Exception { addLibrarySubmodule(); ObjectId newHead = library.commit().setMessage( "msg" ).call(); File workDir = parent.getRepository().getWorkTree(); Git libModule = Git.open( new F‌ile( workDir, "modules/library" ) ); libModule.pull().call(); libModule.close(); parent.add().addF‌ilepattern( "modules/library" ).call(); parent.commit().setMessage( "Update submodule" ).call(); assertEquals( newHead, getSubmoduleHead( "modules/library" ) );}这个较长的代码片段中,首先第一件事就是提交一些东西到library仓库中(第四行),接着将子模块更新到最近的一次提交。为了让这种更新持久化保存下来,子模块必须被提交(第10,11行)。这次提交在子模块的名下(例子中是modules/library)保存了此次更新的commit-id。最后,通常需要将修改push上去,使得他们对其他仓库可用。在父仓库中更新对子模块的修改将上游的提交拉取到父仓库中也会修改子模块的配置。然而子模块本身并不会自动得到更新。SubmoduleUpdateCommand就是用来解决这个问题。使用这个命令并不需要指定其他参数,它会更新所有已注册的子模块。该命令会克隆缺失的子模块并检出其配置中指定的提交。就如其他子模块命令一样,这里也有一个addPath()方法,以保证只更新给定路径下的子模块。克隆一个包含子模块的仓库此时你可能已经掌握一个规律,所有对子模块的操作都是手动的。克隆一个包含子模块配置的仓库并不会默认克隆它的子模块。但是,CloneCommand命令有一个cloneSubmodules的属性,如果设置为true,那么将会克隆所有配置的子模块。从内部看,在对父仓库进行克隆之后,SubmoduleInitCommand和SubmoduleUpdateCommand命令会被递归地执行,并且父仓库的工作目录会被检出。移除一个子模块如果要移除一个子模块,你会希望可以这样写:1 git.submoduleRm().setPath( ... ).call();但是很不幸,不管是原生的Git或者JGit都没有提供内置的移除子模块的指令,希望将来会添加这样的指令,在这之前,我们必须手动去移除子模块。如果你滚动到removeSubmodule()方法你会发现这并不是一件复杂的事。首先,各个子模块会从.gitsubmodules和.git/config配置文件中移除。其次,子模块的入口会从索引中被移除。最后,.gitsubmodules文件以及索引的修改会被提交,并且子模块的内容会从工作目录中删除。遍历子模块原生的Git提供了git submodule foreach命令为每个子模块执行一个shell指令。JGit并没有直接支持这样的指令,而是提供了SubmoduleWalk。该类可以用来迭代仓库中子模块。以下示例程序实现了为所有子模块拉取上游的提交。1234567891011121314151617 @Testpublic void testSubmoduleWalk() throws Exception { addLibrarySubmodule(); int submoduleCount = 0; Repository parentRepository = parent.getRepository(); SubmoduleWalk walk = SubmoduleWalk.forIndex( parentRepository ); while( walk.next() ) { Repository submoduleRepository = walk.getRepository(); Git.wrap( submoduleRepository ).fetch().call(); submoduleRepository.close(); submoduleCount++; } walk.release(); assertEquals( 1, submoduleCount );}通过next()方法walk对象可以指向下一个子模块,如果没有更多的子模块,该方法会返回false。使用SubmoduleWalk时,通过调用release()方法可以释放子模块相关的资源。再次强调,如果你获得一个子模块的仓库实例可别忘了关闭它。SubmoduleWalk也可以用来获取子模块的详细信息。通过它的大部分getter方法可以访问到当前子模块的属性,诸如path,head,remote URL等等。同步远程URL从上面我们知道子模块的配置保存在父仓库根工作目录下的.gitsubmodules文件中。而至少,在.git/config文件中,我们可以重写覆盖子模块的远程URL。对于每个子模块,它们本身都有一个配置文件。那么反过来,每个子模块可以有另一个远程URL。SubmoduleSyncCommand命令可以用来将所有远程URL重置为.gitmodules中的配置。综上所述,JGit对子模块的支持几乎与原生的Git一致。大部分Git指令都在JGit中实现了,或可以通过一些途径进行仿真。如果你发现一些操作缺失或实现不了,可以去友好且帮得上忙的JGit社区去寻求帮助www.zgxue.com防采集请勿采集本网。

使用场景

当项目越来越庞大之后,不可避免的要拆分成多个子模块,我们希望各个子模块有独立的版本管理,并且由专门的人去维护,这时候我们就要用到git的submodule功能。

Git 1.8.2提供了一个新的选项--remote,可以完全实现这种行为。运行 git submodule update --remote --merge 将从每个子模块的上游获取最新更改,并将其合并,并检查子模块的最新版本。正如文件所说: - 远程 该选项仅对更新命令有效。使用子模

常用命令

git 的 submodule 方式不会向仓库添加实际的的内容的,只会通过 .gitmodules 文件保留相应的子模块的哈希值。 由于你要真正要用的代码处于一个子目录中,我的方案是你先把这个子目录提取成一个单独的仓库(可以使用 git-subtree.sh 这个脚本),

git clone <repository> --recursive 递归的方式克隆整个项目git submodule add <repository> <path> 添加子模块git submodule init 初始化子模块git submodule update 更新子模块git submodule foreach git pull 拉取所有子模块

对于一个较大的Git工程,你可能会想在多个仓库之间共享代码,不管这些代码是在多个不同产品间使用的项目共享库或是一些模板。Git通过子模块来实现这样的需求。子模块允许将其他代码仓库的克隆作为子目录放到一个父仓库(有时候也称为父项目)中。

如何使用

1. 创建带子模块的版本库

最近在给考拉山后台添砖加瓦的过程中,发现了两个问题: 对于当前的同一套逻辑,我已经有4个view层工作在上面了,马上还要再加上一个view,专门用来显示分享出去的页面; 接下来还要再加上同步evernote这种异步任务; 而现在这些代码都还在同一

例如我们要创建如下结构的项目

删除子模块:(分4步走) 1) $ Git rm --cached [path] 根据路径删除子模块的记录 2) 编辑“.gitmodules”文件,将子模块的相关配置节点删除掉 清理子模块配置 3) 编辑“ .git/config”文件,将子模块的相关配置节点删除掉 清理子模块配置 4) 手动删

project |--moduleA |--readme.txt

创建project版本库,并提交readme.txt文件

git init --bare project.gitgit clone project.git project1cd project1echo "This is a project." > readme.txtgit add .git commit -m "add readme.txt"git push origin mastercd ..

创建moduleA版本库,并提交a.txt文件

git init --bare moduleA.gitgit clone moduleA.git moduleA1cd moduleA1echo "This is a submodule." > a.txtgit add .git commit -m "add a.txt"git push origin mastercd ..

在project项目中引入子模块moduleA,并提交子模块信息

cd project1git submodule add ../moduleA.git moduleAgit statusgit diffgit add .git commit -m "add submodule"git push origin mastercd ..

使用git status可以看到多了两个需要提交的文件,其中.gitmodules指定submodule的主要信息,包括子模块的路径和地址信息,moduleA指定了子模块的commit id,使用git diff可以看到这两项的内容。这里需要指出父项目的git并不会记录submodule的文件变动,它是按照commit id指定submodule的git header,所以.gitmodules和moduleA这两项是需要提交到父项目的远程仓库的。

On branch masterYour branch is up-to-date with 'origin/master'.Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: .gitmodules new file: moduleA

2. 克隆带子模块的版本库

方法一,先clone父项目,再初始化submodule,最后更新submodule,初始化只需要做一次,之后每次只需要直接update就可以了,需要注意submodule默认是不在任何分支上的,它指向父项目存储的submodule commit id。

git clone project.git project2cd project2git submodule initgit submodule updatecd ..

方法二,采用递归参数--recursive,需要注意同样submodule默认是不在任何分支上的,它指向父项目存储的submodule commit id。

git clone project.git project3 --recursive

3. 修改子模块

修改子模块之后只对子模块的版本库产生影响,对父项目的版本库不会产生任何影响,如果父项目需要用到最新的子模块代码,我们需要更新父项目中submodule commit id,默认的我们使用git status就可以看到父项目中submodule commit id已经改变了,我们只需要再次提交就可以了。

cd project1/moduleAgit branchecho "This is a submodule." > b.txtgit add .git commit -m "add b.txt"git push origin mastercd ..git statusgit diffgit add .git commit -m "update submodule add b.txt"git push origin mastercd ..

4. 更新子模块

更新子模块的时候要注意子模块的分支默认不是master。

方法一,先pull父项目,然后执行git submodule update,注意moduleA的分支始终不是master。

cd project2git pullgit submodule updatecd ..

方法二,先进入子模块,然后切换到需要的分支,这里是master分支,然后对子模块pull,这种方法会改变子模块的分支。

cd project3/moduleAgit checkout mastercd ..git submodule foreach git pullcd ..

5. 删除子模块

网上有好多用的是下面这种方法

git rm --cached moduleArm -rf moduleArm .gitmodulesvim .git/config

删除submodule相关的内容,例如下面的内容

[submodule "moduleA"] url = /Users/nick/dev/nick-doc/testGitSubmodule/moduleA.git

然后提交到远程服务器

git add .git commit -m "remove submodule"

但是我自己本地实验的时候,发现用下面的方式也可以,服务器记录的是.gitmodules和moduleA,本地只要用git的删除命令删除moduleA,再用git status查看状态就会发现.gitmodules和moduleA这两项都已经改变了,至于.git/config,仍会记录submodule信息,但是本地使用也没发现有什么影响,如果重新从服务器克隆则.git/config中不会有submodule信息。

git rm moduleAgit statusgit commit -m "remove submodule"git push origin master

到此这篇关于Git Submodule管理项目子模块的使用的文章就介绍到这了,更多相关Git Submodule 子模块内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!

对于一个较大的Git工程,你可2113能会想在多个仓5261库之间共享代码,不管这些代码是在4102多个不同产品间使用的1653项目共享库或是一些模板。Git通过子模块来实现这样的需求。子模块允许将其他代码仓库的克隆作为子目录放到一个父仓库(有时候也称为父项目)中。一个子模块也是一个独立的仓库,你可以像其他仓库一样执行commit,branch,rebase等等操作。JGit提供了实现大部分Git子模块命令的API。我将在这儿给大家介绍这些API。设置本文中用到的代码片段将作为学习测试程序。简单的测试程序有助于理解第三方库是如何工作,以及如何使用新的API。你可以将这些测试程序看做是可控制的试验,帮助你更加直观地发现第三方代码是如何执行的。除此之外,如果你保持编写测试程序,可以帮助你检验第三方代码的新版本。如果你的测试程序涵盖了如何调用这些库,那么第三方代码中不兼容的修改将会尽早展现出来。回到之前的话题,所有的测试程序共享同一个设置,详细信息请查看源代码。现在有一个空的仓库,叫parent,以及另一个仓库叫library。测试程序中,library将会作为子模块添加到parent仓库中。library仓库初始化提交了一个readme.txt文件。测试程序中有一个setUp方法,用来创建这两个仓库,如下所示:1 Git git = Git.init().setDirectory( "/tmp/path/to/repo" ).call();这两个仓库用类型为Git的parent和library变量表示。该类封装了一个仓库并允许访问JGit的所有可用指令。就如较早之前我在这里中提到,每个Commnad类对应于一条原生的Git pocelain指令。调用一个指令需要用到生成器模式。举个例子,执行Git.commit()的结果实际上相当于一个CommitCommand。你可以提供一些必要的参数去调用它的call()方法,从而执行相应的指令。添加一个子模块第一步当然是在一个已有的仓库添加子模块。通过上面提到的setUp步骤,library仓库应当作为子模块添加到parent仓库的modules/library目录下。@Testpublic void testAddSubmodule() throws Exception { String uri = library.getRepository().getDirectory().getCanonicalPath(); SubmoduleAddCommand addCommand = parent.submoduleAdd(); addCommand.setURI( uri ); addCommand.setPath( "modules/library" ); Repository repository = addCommand.call(); repository.close(); F‌ile workDir = parent.getRepository().getWorkTree(); F‌ile readme = new F‌ile( workDir, "modules/library/readme.txt" ); F‌ile gitmodules = new F‌ile( workDir, ".gitmodules" ); assertTrue( readme.isF‌ile() ); assertTrue( gitmodules.isF‌ile() );}SubmoduleAddCommand对象需要知道两件事,第一是子模块从哪里克隆而来,第二是它应该存放在哪里。URI属性表示仓库库的克隆地址,这个克隆地址将会传递给clone命令。path属性则指定了相对于parent仓库根工作目录的路径,子模块将被存放在这个路径。这个指令执行之后,parent仓库的工作目录将会变成这样:library仓库存放在modules/library目录下,而且它的工作目录树被检出。call()方法返回一个Repository对象,你可以把它当做一个常规的仓库来使用。这也意味着,你必须在程序中明确显式地关闭返回的仓库,以避免文件句柄泄露。从上图我们可以看到,SubmoduleAddCommand做了一件事,它在parent仓库的根工作目录下创建了一个.git模块文件,并把它添加到索引中内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • git中submodule子模块的添加、使用和删除的示例代码
  • 详解git submodule使用以及注意事项
  • git submodule使用完整教程(小结)
  • hello world程序集锦
  • atom-ide 的使用方法简单介绍
  • 网站搜索框使用微信扫码功能
  • 微信小程序开发实例详解
  • delphi - indy idmessage和idsmtp实现邮件的发送
  • 在codeigniter中 在ci中引入外部的js与css呢
  • win10安装anaconda+tensorflow2.0-cpu+pycharm的图文教程
  • ssl常用专业缩略语汇总
  • 字符编码详解(基础)
  • matlab读取串口数据并显示曲线的实现示例
  • 如何用JGit管理Git子模块
  • 如何用jgit管理git子模块
  • 如何管理git submodule 的版本
  • git submodule 怎么用
  • 如何将Git子模块更新为最新的原始提交
  • 如何把一个工程中的某个目录添加为git submodule
  • 如何用 JGit 管理 Git 子模块
  • 如何把GIT仓库的子目录独立为子模块
  • 如何从git中移除一个子模块
  • git 查看是否有 submodule
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全javascriptasp.netphp编程ajax相关正则表达式asp编程jsp编程编程10000问css/htmlflex脚本加解密web2.0xml/rss网页编辑器相关技巧安全相关网页播放器其它综合dart首页git中submodule子模块的添加、使用和删除的示例代码详解git submodule使用以及注意事项git submodule使用完整教程(小结)hello world程序集锦atom-ide 的使用方法简单介绍网站搜索框使用微信扫码功能微信小程序开发实例详解delphi - indy idmessage和idsmtp实现邮件的发送在codeigniter中 在ci中引入外部的js与css呢win10安装anaconda+tensorflow2.0-cpu+pycharm的图文教程ssl常用专业缩略语汇总字符编码详解(基础)matlab读取串口数据并显示曲线的实现示例最新idea2020注册码永久激活(激活intellij idea2020永久破解,亲测intellij idea激活码获取方法(i删除svn三种方法delsvn(windows+c/s和b/s两种架构的概念、区别和网址(url)支持的最大长度是多少intellij idea 2020最新注册码(亲5个linux平台程序员最爱的开发工url中斜杠/和反斜杠\的区别小结微信公众平台开发——群发信息unicode编码大揭秘详解git submodule使用以及注意事项oauth 2.0授权协议详解微信小程序应用号开发教程详解c、c++、java到python,编程入门学习什么语99%的程序员都会收藏的书单 你读过几本?flask+layui+echarts实现前端动态图展示数hello world程序集锦256种编程语言大汇总
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved