【转】git submodule 与 git subtree

本文介绍了如何使用Git submodule和subtree进行代码管理和版本控制。包括添加、更新、删除子模块的操作步骤,以及如何利用subtree实现跨项目代码的同步更新。

git submodule

转自:http://blog.youkuaiyun.com/wangjia55/article/details/24400501

开发过程中,经常会有一些通用的部分希望抽取出来做成一个公共库来提供给别的工程来使用,而公共代码库的版本管理是个麻烦的事情。今天无意中发现了git的git submodule命令,之前的问题迎刃而解了。

添加

为当前工程添加submodule,命令如下:

git submodule add 仓库地址 路径

其中,仓库地址是指子模块仓库地址,路径指将子模块放置在当前工程下的路径。 
注意:路径不能以 / 结尾(会造成修改不生效)、不能是现有工程已有的目录(不能順利 Clone)

命令执行完成,会在当前工程根路径下生成一个名为“.gitmodules”的文件,其中记录了子模块的信息。添加完成以后,再将子模块所在的文件夹添加到工程中即可。

删除

submodule的删除稍微麻烦点:首先,要在“.gitmodules”文件中删除相应配置信息。然后,执行“git rm –cached ”命令将子模块所在的文件从git中删除。

下载的工程带有submodule

当使用git clone下来的工程中带有submodule时,初始的时候,submodule的内容并不会自动下载下来的,此时,只需执行如下命令:

git submodule update --init --recursive

即可将子模块内容下载下来后工程才不会缺少相应的文件。

What if I want the links to always point to the HEAD of the external repo?

You can make a submodule to follow the HEAD of a branch of a submodule remote repo, with:

git submodule add -b <branch> <repository> [<path>]. (to specify a branch to follow)
git submodule update --remote which will update the content of the submodule to the latest HEAD from <repository>/<branch>, by default origin/master. Your main project will still track the hashes of the HEAD of the submodule even if --remote is used though.


git subtree

转自:https://segmentfault.com/a/1190000003969060

1、初始化子项目Subtree

通过

cd P1项目的路径
git subtree add --prefix=用来放S项目的相对路径 S项目git地址 xxx分支

这样的命令,把S项目(我们姑且叫他S项目)的代码下载到--prefix所指定的目录——我们姑且叫他S目录把,并在P1项目里自动产生一个commit(就是把S目录的内容提交到P1项目里)。

对于P2项目也做同样的操作

2、像往常一样更新代码

大家在P1项目里各种提交commit,其中有些commit会涉及到S目录的更改,正如前面提到的,这是没任何关系的,大家也不会感受到有任何不一样。

3、提交更改到子项目的Git服务器

关键的地方来了:
当维护这个S项目 Subtree 的人希望把最近这段时间对S目录的更改提交到S项目的 Git 服务器上时,他执行一段类似于这样的命令:

cd P1项目的路径
git subtree push --prefix=S项目的路径 S项目git地址 xxx分支

Git 会遍历所有的commit,从中找出针对S目录的更改,然后把这些更改记录提交到S项目的Git服务器上

4、更新子项目新的代码到父项目

OK,现在S项目有大量的新代码了,P2项目也想使用这些新代码,维护P2这个Subtree的人只要执行:

git subtree pull --prefix=S项目的路径 S项目git地址 xxx分支

这样就可以将P2项目里S项目目录里的内容更新为S项目xxx分支的最新代码了。

我总结的 Git Subtree 简明使用手册

假设,你要在各个项目里的components/zenjs这个目录对 http://github.com/youzan/zenjs.git 这个项目做Subtree

1.首先必须确保各个项目已经添加zenjs 这个 remote(关于remote是什么可以看这里):

git remote add zenjs http://github.com/youzan/zenjs.git

2.将zenjs添加到各个项目里

git subtree add --prefix=components/zenjs zenjs master 

3.各项目更新zenjs代码的方法:

git subtree pull --prefix=components/zenjs zenjs master

4.各项目提交zenjs代码的方法:

git subtree push --prefix=components/zenjs zenjs hotfix/zenjs_xxxx

这会在远程的zenjs的仓库里生成一个叫 hotfix/zenjs_xxxx 的的分支,包含了你过去对components/zenjs 所有的更改记录

5.把hotfix/zenjs_xxx分支更新并合并到master并提交

这样其他工程就可以更新到你提交的代码了。

有人可能会问,只用master分支,不管版本,太有风险了。

对的,正如我们前面说到的那样,subtree的方案适用的场景是:各个项目共用一个库,而这个库正在快速迭代更新的过程中。如果追求稳定,只需要给库拉出一个如v0.1.0这样的版本号命名的稳定分支,subtree只用这个分支即可。

我们现在使用的方式就是:A项目经常会对zenjs做更新,所以A项目用subtree来双向同步;B项目只是使用,所以用bower用来按版本来更新代码。

高阶功能

重新split出一个新起点(这样,每次提交subtree的时候就不会从头遍历一遍了)

git subtree split --rejoin --prefix=components/zenjs --branch new_zenjs
git push zenjs new_zenjs:master


<think> 首先,用户的问题是:“git submodule update git submodule update --remote区别”,我需要用中文回答。 我的回答必须完整覆盖问题,然后结束时必须提出3-5个相关问题。相关问题的第一行必须是“§§相关问题§§”,能换行分散,必须一行输出。 回顾示例格式:回答完问题后,直接输出“§§相关问题§§”,然后列出1. 2. 3. 等问题。问题用数字列表,每个问题以点开头(如1. ···)。 现在,问题核心是解释git submodule updategit submodule update --remote的区别。 关键点: - git submodule update:默认行为是更新子模块到父仓中记录的commit(即.gitmodules文件中的commit)。它会自动获取远程更新;只是检出到指定的commit。 - git submodule update --remote:这个选项会先获取子模块的远程仓的最新更改,然后检出到远程分支(通常是origin/HEAD或配置的分支),并更新父仓的子模块commit引用。 我需要结构化回答: 1. 简介git子模块是什么(简要)。 2. 解释git submodule update。 3. 解释git submodule update --remote。 4. 比较两者的区别。 用中文回答。 回答格式: - 先回答问题。 - 结束时输出“§§相关问题§§”一行。 - 然后列出3-5个相关问题。 相关问题必须基于用户的问题我的回答。用户问题是关于git submodule update的区别,所以相关问题应该围绕git子模块的使用、最佳实践、相关问题等。 头脑风暴相关问题: 1. 如何在git子模块中指定特定分支? 2. 使用git submodule update --remote时如何避免冲突? 3. git子模块git子树的区别是什么? 4. 在实际项目中,管理多个git子模块的最佳实践是什么? 5. 如何初始化一个新的git子模块? 确保3-5个,所以选择4个吧。 最终输出: - 回答内容。 - “§§相关问题§§” - 1. ... 2. ... 3. ... 4. ... 使用中文。 撰写回答: 先解释: git submodule update:这个命令用于更新子模块到父仓中指定的commit。它会从远程拉取最新代码;只是检出到提交历史中记录的commit。 git submodule update --remote:这个命令会首先从子模块的远程仓获取最新更新,然后检出到远程跟踪分支(默认是origin/master或配置的分支),并更新父仓的子模块commit引用以匹配。 区别: - update 只更新到本地记录的commit。 - update --remote 更新到远程最新,并修改父仓引用。 完整回答: ### git submodule update git submodule update --remote 的区别 在 Git 中,子模块(submodule)允许将一个 Git作为另一个仓的子目录嵌入。管理子模块时,`git submodule update` `git submodule update --remote` 是常用的命令,但它们在行为上有本质区别: 1. **git submodule update** - **功能**:此命令会将每个子模块更新(检出)到父仓中记录的特定 commit(即 `.gitmodules` 文件或父仓索引中指定的提交)。 - **行为**: - 如果子模块尚未初始化或克隆,它会先克隆子模块。 - 它会从远程仓获取最新更改;只检出到父仓指定的 commit。 - 常用于确保子模块状态父仓提交一致(例如,在切换分支后)。 - **示例场景**:当你在父仓执行 `git checkout` 切换到同分支后,运行此命令可使子模块对齐到新分支的记录。 2. **git submodule update --remote** - **功能**:此命令会主动从子模块的远程仓获取最新提交,并更新子模块到远程分支(默认是 `origin/HEAD` 或配置的分支)。同时,它会更新父仓中子模块的引用。 - **行为**: - 首先,从子模块的远程仓拉取(fetch)最新数据。 - 然后,检出到远程跟踪分支(如 `origin/main`)。 - 最后,将父仓中子模块的 commit 引用更新为最新拉取的 commit(需要后续提交父仓)。 - 相当于对每个子模块执行 `git pull`。 - **示例场景**:如果你想将子模块同步到最新上游版本时使用(需谨慎,避免破坏兼容性)。 **核心区别总结**: - `git submodule update`:**被动同步**,仅对齐到父仓记录的 commit,涉及远程更改。 - `git submodule update --remote`:**主动更新**,拉取远程最新提交并修改父仓引用(需提交更改)。 - **关键差异**:后者会改变父仓的状态(需要 commit 新子模块引用),前者会。 现在,结束回答,输出相关问题。 相关问题: 1. 如何配置git子模块以使用特定远程分支? 2. 在使用git submodule update --remote后,如何处理父仓的提交? 3. git子模块git subtree在版本控制中有何优缺点比较? 4. 在团队协作中,管理git子模块的最佳实践是什么? 5. 如何避免git子模块在切换分支时出现冲突? 确保3-5个,我列出了5个,但可以减少到4个以防万一。 输出时,“§§相关问题§§”必须一行,然后直接数字列表。 </think> ### git submodule update git submodule update --remote 的区别 在 Git 中,子模块(submodule)用于将一个 Git作为另一个仓的子目录嵌入。这两个命令都用于更新子模块,但行为有显著差异: 1. **git submodule update** - **功能**:将子模块更新(检出)到父仓中记录的 **特定 commit**(该 commit 保存在父仓的 `.gitmodules` 文件或索引中)。 - **行为细节**: - 会从远程仓(如 GitHub)自动获取最新更改;仅检出到父仓指定的 commit。 - 如果子模块未初始化,它会先克隆子模块到本地。 - 适用于恢复子模块状态以匹配父仓的当前提交(例如,在 `git checkout` 切换分支后)。 - **安全性**:确保子模块版本父仓代码兼容,但可能落后于远程最新版。 2. **git submodule update --remote** - **功能**:从子模块的远程仓获取最新提交,并更新子模块到 **远程跟踪分支的 HEAD**(默认是 `origin/main` 或配置的分支),同时修改父仓的子模块引用。 - **行为细节**: - 先执行 `git fetch` 拉取远程最新数据。 - 然后检出到远程分支的最新 commit。 - 最后更新父仓中子模块的 commit 记录(需后续提交父仓以保存变更)。 - 相当于对每个子模块自动运行 `git pull`。 - **适用场景**:当需要主动同步子模块到上游最新代码时(例如,修复安全漏洞),但需注意可能引入兼容性问题。 **核心区别总结**: - **更新目标**: - `update` 对齐到 **父仓记录的 commit**(本地操作)。 - `update --remote` 对齐到 **远程仓最新 commit**(网络依赖操作)。 - **父仓影响**: - `update` 会修改父仓的提交历史。 - `update --remote` 会更新父仓的子模块引用,必须通过 `git commit` 提交变更。 - **典型用例**: - 用 `update` 确保团队一致性(如协作开发)。 - 用 `update --remote` 主动升级依赖(如第三方更新)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值