当前位置: 首页 > web >正文

使用子树合并策略更新git项目的部分目录

背景

正在开发的一个项目中引用了第三方库的源码,由于历史原因,源码的引用并不是很规范(直接下载下来后作为自己项目的部分源码使用,还进行了一些修改),具体如下:

  1. 我有一个本地git项目project_local,其基本目录结构如下:
    project_local
    |-- CHANGELOG.md
    |-- CMakeLists.txt
    |-- README.md
    |-- jsoncpp
    |   |-- CMakeLists.txt
    |   |-- json
    |   `-- jsoncpp.cpp
    |-- thread_pool.h
    `-- vpf|-- CMakeLists.txt|-- FindVPF.cmake|-- PyNvCodec|-- PytorchNvCodec|-- VideoCapture.cpp|-- VideoCapture.h|-- VideoWriter.cpp`-- VideoWriter.h
    
    其中,vpf/PyNvCodec、vpf/PytorchNvCodec均为目录,下面还有子目录和各种文件,正是这两个目录来源于开源项目
  2. 线上github源码工程为project_online,其基本目录结构为:
    project_online
    |-- CMakeLists.txt
    |-- LICENSE
    |-- PyNvCodec
    |   |-- CMakeLists.txt
    |   |-- TC
    |   |-- inc
    |   |-- pybind11-2.1.1
    |   `-- src
    |-- PytorchNvCodec
    |   |-- CMakeLists.txt
    |   `-- src
    |-- README.md
    |-- SampleDecode.py
    |-- SampleDecodeMultiThread.py
    |-- SampleDecodeSw.py
    |-- SampleDemuxDecode.py
    |-- SampleEncode.py
    |-- SampleEncodeMultiThread.py
    |-- SamplePyTorch.py
    |-- SampleTensorRTResnet.py
    |-- SampleTorchResnet.py
    `-- Tests.py
    
  3. project_local项目中的vpf目录使用了project_online工程,即vpf/PyNvCodec、vpf/PytorchNvCodec两个目录均来源于project_online项目下的PyNvCodec和PytorchNvCodec
  4. 具体需要求是:project_online项目有更新了(新版本v1.1),我想把这些更新应用在vpf/PyNvCodec、vpf/PytorchNvCodec这两个目录上,其他文件和目录均保持不变

实现方法

推荐方法:推荐方法:使用子树合并策略 (Subtree Merge)

# 进入本地项目目录
cd /path/to/project_local# 1. 添加原始仓库为远程源
git remote add online https://github.com/original-owner/project_online.git
git fetch online# 2. 选择要合并的版本(标签或分支)
TARGET_VERSION="v1.1"  # 替换为实际版本# 3. 更新 PyNvCodec
git subtree pull --prefix=vpf/PyNvCodec online $TARGET_VERSION -m "Update PyNvCodec to $TARGET_VERSION"# 4. 更新 PytorchNvCodec
git subtree pull --prefix=vpf/PytorchNvCodec online $TARGET_VERSION -m "Update PytorchNvCodec to $TARGET_VERSION"# 5. 保留本地修改的文件(根据情况看是否执行)
git checkout HEAD -- vpf/PyNvCodec/local_settings.py
git checkout HEAD -- vpf/PytorchNvCodec/custom_config.h

这种方法确保:

  1. 精确更新指定目录
  2. 保留本地其他文件的修改
  3. 维护清晰的提交历史
  4. 支持后续持续更新
  5. 提供冲突解决机制

其他

关于git subtree pull 命令详解:

git subtree pull --prefix=vpf/PyNvCodec online $TARGET_VERSION -m "Update PyNvCodec to $TARGET_VERSION" 这个命令是 Git 子树策略的核心操作之一,下面我将详细解释其工作原理和每个参数的作用。

命令结构解析

命令部分说明
git subtree pull子树拉取操作
--prefix=vpf/PyNvCodec指定本地目标目录
online远程仓库别名
$TARGET_VERSION要拉取的远程版本(分支/标签)
-m "Update PyNvCodec to $TARGET_VERSION"合并提交信息

工作原理详解

1. 子树合并的本质

git subtree 是一种将外部仓库作为子目录集成到当前仓库的策略。与子模块不同,子树的内容直接属于主仓库,不需要额外的引用文件。

2. 命令执行流程

当执行 git subtree pull 时,Git 会执行以下操作:

  1. 创建临时分支:在后台创建一个临时分支,包含远程仓库指定版本的内容
  2. 提取子树历史:从临时分支中提取与指定目录相关的提交历史
  3. 重写路径:将远程路径重写为本地 --prefix 指定的路径
    • 远程:PyNvCodec/file.txt → 本地:vpf/PyNvCodec/file.txt
  4. 合并到当前分支:将重写后的提交合并到当前分支
  5. 创建合并提交:使用 -m 指定的消息创建合并提交
  6. 清理临时对象:删除临时分支和相关对象

3. 路径映射机制

原始远程结构:         本地映射后结构:
PyNvCodec/            vpf/PyNvCodec/
├── src/              ├── src/
├── inc/              ├── inc/
└── CMakeLists.txt    └── CMakeLists.txt

Git 会自动处理路径转换,确保远程文件放入正确的本地目录。

关键特性与优势

1. 历史保留

  • 保留完整的提交历史(包括作者、日期等信息)
  • 可以通过 git log vpf/PyNvCodec 查看子树历史
  • 保持原始提交哈希不变(通过重写实现)

2. 双向同步

  • 拉取更新git subtree pull
  • 推送修改git subtree push --prefix=... online branch
  • 允许将本地修改推送回原始仓库

3. 冲突处理

当子树目录有本地修改时:

  1. Git 会自动尝试合并
  2. 如果自动合并失败,会暂停并提示解决冲突
  3. 解决冲突后使用 git commit 完成合并

4. 与普通合并的区别

特性git subtree pull普通 git merge
影响范围仅指定目录整个仓库
历史处理重写路径后保留原始历史保留原始路径
冲突概率更低(仅限子树目录)更高(整个仓库)
工作目录不需要干净状态需要干净状态

使用示例场景

初始添加子树

# 首次添加子树(创建初始提交)
git subtree add --prefix=vpf/PyNvCodec online v1.0.0 -m "添加PyNvCodec v1.0.0"

更新子树

# 更新到新版本
git subtree pull --prefix=vpf/PyNvCodec online v1.2.0 -m "更新PyNvCodec到v1.2.0"

处理冲突

# 如果发生冲突
git mergetool -t vscode  # 使用VS Code解决冲突
git commit -m "解决PyNvCodec合并冲突"

查看子树历史

git log --graph --oneline --decorate -- vpf/PyNvCodec

高级选项

1. 压缩历史 (--squash)

git subtree pull --prefix=... --squash -m "更新"
  • 优点:创建一个合并提交,不引入外部历史,保持仓库整洁
  • 缺点:丢失详细提交历史,无法追溯子树内部变更

2. 指定合并策略

git subtree pull --prefix=... -X theirs  # 优先使用远程版本
git subtree pull --prefix=... -X ours    # 优先使用本地版本

3. 拆分子树历史

# 查看子树历史
git subtree split --prefix=vpf/PyNvCodec --rejoin

常见问题解决方案

  1. 目录不存在错误

    mkdir -p vpf/PyNvCodec  # 确保目标目录存在
    touch vpf/PyNvCodec/.gitkeep  # 添加占位文件
    git add vpf/PyNvCodec/.gitkeep
    git commit -m "创建PyNvCodec目录"
    
  2. 权限拒绝错误

    # 确保没有未提交的修改
    git status# 暂存当前修改
    git stash# 执行子树拉取
    git subtree pull ...# 恢复暂存修改
    git stash pop
    
  3. 大型仓库优化

    # 浅层克隆历史
    git subtree pull --prefix=... --squash# 限制历史深度
    git config subtree.online.shallow true
    

与替代方案的比较

方案优点缺点
子树策略无需外部依赖,完整历史学习曲线较陡峭
子模块明确分离,易于更新需要额外命令,协作复杂
手动复制简单直观丢失历史,难以更新
仓库合并保留完整历史污染主仓库历史

git subtree pull 是管理项目内嵌外部代码库的专业解决方案,特别适合需要保留历史同时精确控制更新范围的情况。

http://www.xdnf.cn/news/12278.html

相关文章:

  • ignore文件不生效的问题
  • 初识硬编码(x86指令描述)
  • 代码随想录算法训练营第九天| 151.翻转字符串里的单词、55.右旋转字符串 、字符串总结
  • CLIP多模态大模型的优势及其在边缘计算中的应用
  • 实时云渲染解决UE像素流送无法进行二次开发的问题
  • spring注解之配置注解
  • 《图解技术体系》How Redis Architecture Evolves?
  • 【科研绘图系列】R语言绘制和弦图(Chord diagram plot)
  • 大模型数据流处理实战:Vue+NDJSON的Markdown安全渲染架构
  • 高防服务器能够抵御哪些网络攻击呢?
  • 宠物空气净化器哪个好用?2025宠物空气净化器测评:352、希喂、有哈
  • 智慧园区数字孪生全链交付方案:降本增效30%,多案例实践驱动全周期交付
  • 基于正点原子阿波罗F429开发板的LWIP应用(5)——TFTP在线升级功能
  • Spring之事务管理方式
  • Go中的协程并发和并发panic处理
  • GitHub 趋势日报 (2025年06月04日)
  • Linux --环境变量,虚拟地址空间
  • 强化学习在LLM中应用:RLHF、DPO
  • 网络通信核心概念全解析:从IP地址到TCP/UDP实战
  • 面试题:Java多线程并发
  • JAVA之 Lambda
  • chrome使用手机调试触屏web
  • Nginx学习笔记
  • 【Go语言基础【2】】数据类型之基础数据类型:数字、字符、布尔、枚举、自定义
  • Unity3D中Newtonsoft.Json序列化优化策略
  • [蓝桥杯]倍数问题
  • 倍福 PLC程序解读
  • kubectl 命令
  • docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(2)
  • 游戏设计模式 - 子类沙箱