git subtree使用基本操作及--squash

本文详细介绍使用Git subtree进行子项目管理的方法,包括初始化、拉取、推送及移除子项目流程。并深入探讨在父项目修改子项目文件时可能遇到的冲突问题,以及如何正确解决这些冲突,避免错误的push操作。

#查看关联的远程仓库的详细信息
git remote -v

一、初始化subtree项目步骤

 1、语法:git remote add -f <子仓库名> <子仓库地址>

     解释:其中-f意思是在添加远程仓库之后, 立即执行fetch.

例如:

git remote add -f proto git@gitee.com:zkh201/zkh-proto.git
2、语法:git subtree add --prefix=<子目录名> <子仓库名> <分支> –-squash

     解释:–squash意思是把subtree的改动合并成一次commit, 这样就不用拉取子项目完整的历史记录. –prefix之后的=等号也可以用空格.

注意:子目录名不需要提前建立好

例如:

–prefix可以使用-P来替换

git subtree add --prefix=zkh-netty/src/main/resources/protobuf proto master --squash
或
git subtree add -P zkh-netty/src/main/resources/protobuf proto master --squash

二、pull subtree项目(需在proto文件夹的父目录执行)

语法:git subtree pull --prefix=<子目录名> <远程分支> <分支> –-squash
例如:

git subtree pull --prefix=zkh-netty/src/main/resources/protobuf proto --squash

三、push subtree项目

语法:git subtree push --prefix=<子目录名> <远程分支> <分支>
注意:子目录中只能修改其中的文件,自己新添加的文件不会纳入到git的管理中
例如:

git subtree push --prefix=zkh-netty/src/main/resources/protobuf proto master

四、移除subtree项目

 删除关联的subtree的git地址即可

语法:
git remote remove name
例如:

git remote remove proto

然后删除相应的文件

遇到的问题(这个很重要):
在这里插入图片描述
(我再描述一下这个冲突:父项目修改了子项目中的文件,然后子项目做了更新且成功,然后子项目又做了一次提交然后push,父项目进行更新此时就出现了冲突,是不是很莫名其妙)是为什么会出现冲突的呢?
现在对上方图片进行描述:
上面的步骤可以分为两种情况:
1、更新父项目中的文件

  • 修改父项目中的文件,提交,push
  • 子项目修改文件,提交,push
  • 父项目进行更新(git subtree pull -P 目录名 子项目远程分支 分支 --squash)

这种情况下不会出现冲突
2、在父项目修改了子项目中的文件

  • 修改父项目下的子项目的文件,提交,push
  • 子项目下更新刚才的提交
  • 子项目下修改文件,提交,push
  • 父项目下进行更新(git subtree pull -P 目录名 子项目远程分支 分支 --squash)

这种情况下会出现冲突
这是第一个问题;
结论就是:
commitId:553b5c2和commitId:2a32d43(squash的合并,这是一个独立的提交,和要待合并的提交没关系)在合并时,都修改了相同的文件,所以造成了两者合并时出现冲突(个人猜测,如有读者知晓原因的话,还望在下方评论给出,谢谢)

第二个问题是在第一个问题出现后,然后我们去解决冲突,然后add标记为冲突解决,再去进行push到远程,一般你是会执行git subtree push …的命令,会出现在报错
在这里插入图片描述
会发现又懵了,这又是什么错?
我这边给出解决办法,具体什么原因我也只是懂个大概
你的做法是需要先提交push到父工程上,然后再进行子工程的push
即如下操作:
在这里插入图片描述
使用subtree和–squash的问题描述就这些,望有知道答案的小伙伴能在下方评论区给出,谢谢!!!!!

<think> 我们正在讨论git subtree使用方法。根据引用[1][2],git subtreegit的一个子命令,需要单独安装。但请注意,在较新版本的Git中(大约1.7.11之后),git subtree已经作为内置子命令包含,无需额外安装。如果系统没有,可以按照引用[1]的方法安装。 引用[3][4][5]介绍了git subtree的基本概念和用途: - 与submodule不同,subtree是将子仓库的代码复制到父仓库的一个子目录中,在父仓库中几乎感觉不到子仓库的存在。 - 它适合将一个项目的一部分导出为独立的仓库,或者将另一个仓库作为子树合并到当前仓库。 下面我将详细介绍git subtree使用方法: ### 1. 添加子仓库(子树) 将另一个仓库(例如:https://github.com/example/child-repo.git)作为子树添加到当前仓库的指定目录(例如:lib/child): ```bash git subtree add --prefix=lib/child https://github.com/example/child-repo.git master --squash ``` - `--prefix`指定子目录路径 - 最后是子仓库的URL和分支(这里是master) - `--squash`将子仓库的整个提交历史合并为一个提交,然后合并到父仓库。如果不加,则会将子仓库的所有提交历史都带过来。 ### 2. 从子仓库拉取更新 当子仓库有新的提交时,在父仓库中拉取更新: ```bash git subtree pull --prefix=lib/child https://github.com/example/child-repo.git master --squash ``` 或者,如果已经添加过远程仓库,可以先用`git remote add`添加一个远程别名(如child-repo),然后使用别名: ```bash git subtree pull --prefix=lib/child child-repo master --squash ``` ### 3. 推送更改到子仓库 如果修改了子树目录(lib/child)中的代码,并希望将修改推送到子仓库: ```bash git subtree push --prefix=lib/child child-repo master ``` ### 4. 拆分子树(从父仓库中提取子目录作为独立仓库) 如果要将父仓库中的某个子目录拆分成一个新的独立仓库(即子仓库),可以使用`split`命令: ```bash git subtree split --prefix=lib/child --branch=split-branch ``` 这会将子目录`lib/child`的历史拆分成一个新的分支`split-branch`。然后可以基于这个分支创建新的仓库: ```bash git push https://github.com/example/new-child-repo.git split-branch:master ``` ### 注意事项 1. **冲突处理**:在拉取更新时,可能会遇到冲突,需要手动解决。 2. **历史记录**:使用`--squash`可以保持父仓库的整洁,但会丢失子仓库的详细提交历史;如果不使用,则历史记录完整但可能会使父仓库的历史变得冗长。 3. **子仓库的独立性**:子仓库仍然是一个独立的仓库,可以单独开发。 ### 示例:添加一个子仓库 假设我们要将`https://github.com/jquery/jquery.git`作为子仓库添加到当前项目的`vendor/jquery`目录: ```bash # 添加子仓库(使用squashgit subtree add --prefix=vendor/jquery https://github.com/jquery/jquery.git main --squash # 后续更新 git subtree pull --prefix=vendor/jquery https://github.com/jquery/jquery.git main --squash ``` ### 引用说明 - 安装方法参考[^1] - 基本概念和与submodule的区别参考[^3][^4] - 使用场景和修复问题示例参考[^5] §§相关问题§§ 1. 如何解决git subtree pull时出现的冲突? 2. 如何将现有的子目录拆分为独立的仓库并保留提交历史? 3. 如何在不使用`--squash`的情况下使用git subtree? 4. 如何从父仓库中移除一个子树? </think>### Git Subtree 使用指南 Git subtree 允许将多个仓库作为子目录集成到主仓库中,同时保留完整的提交历史。以下是详细使用方法: --- #### **1. 安装 Git Subtree** ```bash # 进入Git源码目录(仅需在未预装时执行) cd git/contrib/subtree make sudo cp git-subtree /usr/local/bin/ ``` --- #### **2. 添加子树** 将子仓库(如 `https://github.com/user/sub-repo.git`)添加到主仓库的 `sub-dir` 目录: ```bash git subtree add --prefix=sub-dir https://github.com/user/sub-repo.git main --squash ``` - `--prefix`:指定子目录路径 - `--squash`:将子仓库历史合并为单次提交(可选) - `main`:子仓库分支名 --- #### **3. 更新子树** 从子仓库拉取最新更改: ```bash git subtree pull --prefix=sub-dir https://github.com/user/sub-repo.git main --squash ``` --- #### **4. 推送更改到子仓库** 将主仓库中子目录的修改推回子仓库: ```bash git subtree push --prefix=sub-dir https://github.com/user/sub-repo.git main ``` --- #### **5. 拆分仓库** 将主仓库的子目录拆分为独立仓库: ```bash # 创建包含历史的分支 git subtree split --prefix=sub-dir -b split-branch # 推送到新仓库 git push https://github.com/user/new-repo.git split-branch:main ``` --- ### 关键特性对比 | 特性 | `git subtree` | `git submodule` | |---------------------|-----------------------------------|-------------------------------| | **代码存储方式** | 直接复制到主仓库 | 仅存储引用链接 | | **历史记录** | 完整保留子仓库历史 | 独立历史 | | **修改同步** | 双向同步 | 单向更新 | | **工作流复杂度** | 低(类似普通目录) | 高(需额外命令初始化更新) | | **适用场景** | 紧密集成的组件 | 独立开发的插件/依赖库 | --- ### 典型工作流示例 ```mermaid graph LR A[主仓库] --> B[添加子树 git subtree add] B --> C[日常开发修改子目录] C --> D[推送更新到子仓库 git subtree push] D --> E[拉取子仓库更新 git subtree pull] ``` --- ### 常见问题解决 1. **冲突处理** 在 `pull/push` 时添加 `--strategy=recursive -X theirs` 自动接受子仓库变更: ```bash git subtree pull --prefix=sub-dir origin main -X theirs ``` 2. **查看历史记录** ```bash git log --graph --oneline --decorate --prefix=sub-dir/ ``` 3. **移除子树** 直接删除目录并提交: ```bash git rm -r sub-dir git commit -m "移除子树" ``` > 提示:使用 `--squash` 可减少主仓库历史复杂度,但会丢失子仓库详细提交记录[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值