git管理子模块

摘要:
目录Git管理子模块通用命令使用子模块创建项目使用子模块克隆项目修改子模块项目获取子模块项目删除子模块子树通用命令使用个子模块创建项目克隆项目使用子模块修改子模块工程获取子模块工程删除子模块文件软链接Git管理子模块,更新本地仓库中的所有子模块后,子树指向上一次提交。

目录

git管理子模块

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

sumodule是引用,subtree是复制

/submodulesubtree结果
远程仓库空间占用submodule只是引用,基本不占用额外空间子模块copy,会占用较大的额外空间submodule占用空间较小,略优
本地空间占用可根据需要下载会下载整个项目所有模块基本都要下载,二者差异不大
仓库克隆克降后所有子模块为空,需要注册及更新,同时更新后还需切换分支克隆之后即可使用submodule步骤略多,subtree占优
更新本地仓库更新后所有子模块后指向最后一次提交,更新后需要重新切回分支,所有子模块只需一条更新语句即可所有子模块需要单独更新各有优劣,相对subtree更好用一些
提交本地修改只需关心子模块即可,子模块的所有操作与普通git项目相同提交执行命令相对复杂一些submodule操作更简单,submodule占优

submodule

常用命令

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

创建带子模块的项目

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

project
  |--moduleA
  |--readme.txt

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

git init --bare project.git
git clone project.git project
cd project
echo "This is a project." > readme.txt
git add .
git commit -m "add readme.txt"
git push origin master
cd ..

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

git init --bare moduleA.git
git clone moduleA.git moduleA
cd moduleA
echo "This is a submodule." > a.txt
git add .
git commit -m "add a.txt"
git push origin master
cd ..

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

cd project
git submodule add moduleA.git moduleA
git status
git diff
git add .
git commit -m "add submodule"
git push origin master
cd ..

使用git status可以看到多了两个需要提交的文件:.gitmodulesmoduleA。使用git diff可以看到这两项的内容。这里需要指出父项目的git并不会记录submodule的文件变动,它是按照commit id指定submodule的git header,所以.gitmodulesmoduleA这两项是需要提交到父项目的远程仓库的。

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
    new file:   .gitmodules  # 指定submodule的主要信息,包括子模块的路径和地址信息
    new file:   moduleA  # 指定了子模块的commit id

克隆带子模块的项目

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

git clone project.git project
cd project
git submodule init
git submodule update
cd ..

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

git clone project.git project --recursive

项目中修改子模块

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

# 进入子模块进行修改提交
cd project/moduleA
git branch
echo "This is a submodule." > b.txt
git add .
git commit -m "add b.txt"
git push origin master
# 进入项目进行提交
cd ..
git status
git diff
git add .
git commit -m "update submodule add b.txt"
git push origin master
cd ..

项目中获取子模块

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

cd project/moduleA
git checkout master

方法一:子模块更新

cd project/moduleA
git pull

方法二:主目录更新

cd project
git submodule foreach git pull

项目中删除子模块

删除缓存和文件夹

git rm --cached moduleA
rm -rf moduleA
rm .gitmodules
vim .git/config

删除配置信息

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

然后提交到远程服务器

git add .
git commit -m "remove submodule"

subtree

常用命令

git subtree add -P <prefix> <commit>
git subtree add -P <prefix> <repository> <ref>
git subtree pull -P <prefix> <repository> <ref>
git subtree push -P <prefix> <repository> <ref>
git subtree merge -P <prefix> <commit>
git subtree split -P <prefix> [OPTIONS] [<commit>]

参数

-q | --quiet
-d | --debug
-P <prefix> | --prefix=<prefix>      # 引用库对应的本地目录,prefix可以为空
-m <message> | --message=<message>   # 适用于add/pull/merge子命令。设置产生的合并提交的说明文本

squash

--squash                             
#. 适用于add/pull/merge子命令。先合并引用库的更新记录,将合并结果并到主项目中。
# 使用此选项时,把 subtree 子项目的更新记录进行合并,再合并到主项目中:subtree add/pull 操作的结果对应两个commit:一个是squash了子项目的历史记录,一个是 Merge 到主项目中。优点是可以让主项目历史记录很规整,缺点是在子项目需要 subtree pull 的时候,经常需要处理冲突,甚至每次subtree pull的时候都需要重复处理同样的冲突。
# 如果不加 --squash 参数,主项目会合并子项目本身所有的 commit 历史记录。优点是子项目更新的时候,subtree pull 很顺利, 能够自动处理已解决过的冲突。缺点是子项目会污染主项目。
# 一个更好的解决方案是:单独建一个分支进行--no-squash的subtree更新,然后再--squash合并到主分支。每次在此分支做操作前都需要先把主分支合并进来。参考:http://www.fwolf.com/blog/post/246.

split

# split子命令选项:
--annotate=<annotation>              # 创建合成历史时有可能形成内容不同但提交信息完全相同的提交版本,使用这个选项在每个提交消息前加上此前缀用来区分。
-b <branch> | --branch=<branch>      # 创建合成的提交历史时,创建此参数指定的新分支包含生成的合成历史。<branch>必须是还不存在的。
--onto=<onto>
--rejoin
--ignore-joins

创建带子模块的项目

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

project
  |--moduleA
  |--readme.txt

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

git init --bare project.git
git clone project.git project
cd project
echo "This is a project." > readme.txt
git add .
git commit -m "add readme.txt"
git push origin master
cd ..

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

git init --bare moduleA.git
git clone moduleA.git moduleA
cd moduleA1
echo "This is a submodule." > a.txt
git add .
git commit -m "add a.txt"
git push origin master
cd ..

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

git remote add moduleA http://xx.git  # 非必须,便于简化下步操作
git subtree add --prefix=moduleA moduleA master --squash # git subtree add --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <分支> --squash
git push  # 提交

克隆带子模块的项目

git clone project.git project

项目中修改子模块

# git subtree push --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <S项目分支>
git subtree push --prefix=moduleA moduleA master

每次push命令都会遍历全部的commit,当你的项目越来越大,commit的数上来的时候,等待时间就会很长。--rejoin 避免了遍历全部commit的问题.

# git subtree split --rejoin --prefix=<S项目的相对路径> --branch <临时branch>
git subtree split --rejoin --prefix=moduleA --branch srcTemp  # 提取与引用库子目录相关的变更并生成一个新的合成历史到新分支
# git push <S项目远程库仓库地址 | S项目远程库别名> srcTemp:master
git push share srcTemp:master

项目中获取子模块

# git subtree pull --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <分支> --squash
git subtree pull --prefix=src/share share master --squash

项目中删除子模块

删除缓存和文件夹

git rm --cached moduleA
rm -rf moduleA
vim .git/config

删除配置信息

[remote "module"]
      url = git@github.com:fhkankan/moduleA.git
	  fetch = +refs/heads/*:refs/remotes/module/*

然后提交到远程服务器

git add .
git commit -m "remove submodule"

文件软链接

在项目中创建其他仓库的项目的软连接,也可以实现多模块管理,需要注意,部署时,需要将所有代码模块进行同位置下载与维护

cd project
ln -s ../project2 lib1
ln -s ../project2 lib2

免责声明:文章转载自《git管理子模块》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇dbcp连接池配置参数nginx实战三下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C# Wpf集合双向绑定

说明: msdn中   ObservableCollection<T> 类    表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。 在许多情况下,所使用的数据是对象的集合。 例如,数据绑定中的一个常见方案是使用 ItemsControl(如 ListBox、ListView 或 TreeView)来显示记录的集合。 可...

XAML: 在 MVVM 模式中,关于绑定的几处技巧

    以下会提到三个绑定的技巧,分别是 在 ListView 中为 ListViewItem 的 MenuFlyout 绑定 Command; 在 ListView 的 事件中绑定所选择项目,即其 SelectedItem属性; 处理文本控件与数值属性绑定中默认值0的问题; 一、在 ListView 中为列表项的 MenuFlyout 绑定 Comm...

JFileChooser添加文件过滤

这是java的Swing里的一个选择文件的控件,我们要如何使用它?首先来看看JDKAPI的说明: public class JFileChooserextends JComponentimplements Accessible JFileChooser 为用户选择文件提供了一种简单的机制。有关使用 JFileChooser 的更多信息,请参阅 《The...

C# 自定义exe引用的dll路径

MSDN原文:https://msdn.microsoft.com/library/twy1dw1e(v=vs.100).aspx <runtime> 的 <assemblyBinding> 元素 .NET Framework 4                其他版本                           ...

django数据库的增删改查

正常启动服务安装数据库cmd命令:python manage.py makemigrations 创建用户 在pxm里面会有一个py文件..这就是生成了表结构cmd命令:python manage.py migrate 自带的一些表 导入这就是正向导入数据库 反向导入数据库:python manage.py inspectdb > son1/mode...

angular2 支持排序的拖拽组件ng2-dragula

    最近项目上遇到需要拖拽的需求,于是就在github上找了一些相关组件,最后看中了ng2-drag-drop和ng2-dragula,但是ng2-drag-drop组件本身拖拽的时候不支持拖拽元素放在拖拽目标的任意位置,只能放置在拖拽目标那一列的最后。所以最后使用了ng2-dragula。 github地址:https://github.com/va...