跨远程仓库同步代码

0 实现功能

之前的项目是基于一个开源项目做的,后来开源项目一直在更新迭代,所以时不时需要把开源项目的新功能合入到自己的项目中,这样就出现跨项目仓库进行更新,而且这个开源项目也只是自己项目里边的一个子文件夹。
梳理一下功能需求:

  1. 公司项目A,把开源项目B以子文件夹的方式包含进来
  2. 开源项目B一直在维护并更新着
  3. 公司项目A需要把自包含开源项目B之后,开源项目B的修改合并进来

以上需求可以使用Git Subtree实现:

  1. 首先把项目A中以子文件夹存在的开源项目B独立成子项目
  2. 然后使用Git Subtree在需要的时候,直接把开源项目B的修改同步到项目A

1 参考资料

用 Git Subtree 在多个 Git 项目间双向同步子项目
git subtree教程
fork别人的项目保持与源项目同步更新的两种方式

2 Git Subtree

在介绍Git Subtree之前先说一下跟Git Subtree类似的一个功能Git Submodule,对于Git Submodule而言,在本地代码库可能存在多个Git代码仓库,并且有一个.gitmodule的文件记录着父项目添加的子module。

2.1 Sub module vs Sub tree 对比

  1. 对父项目的占用区别:对于父项目而言,如果使用 submodule 会在父项目中新增一个 .gitmodule 的文件来记录父项目添加的子 module,而使用 subtree 则会将子项目完整的克隆到父项目的一个文件夹中。
  2. 在 clone 子项目步骤上:使用 submodule 需要执行多个步骤,在拉取主项目后需要使用 submodule 命令单独更新 submodule;而使用 subtree 则只需要使用 clone 命令
  3. push 子项目:submodule 因为将子项目视为独立的项目,可以直接 push;使用 subtree 则需要手动进行对比
  4. pull 子项目:submodule pull 子项目后需要,在父项目再进行提交 git submodule update --recursive --remote;而使用 subtree 则直接 pull 即可

2.2 为什么要使用 git subtree?

git subtree 可以让一个 repository 嵌入到另一个项目的子目录中:

  • 管理方便,对于项目中的成员无需关心额外的 git 工作流,使用最基本的 git 工作流即可
  • 在拉取代码的时候,一行 clone 命令可以立即获得包括子项目在内的所有的项目文件,而不是像 git submodule 一样还需要额外的 update 命令
  • git subtree 不会像 gitmodule 一样引入 metadata 文件来管理,git subtree 的使用对于项目中其他成员可以透明
  • 子项目中的内容可以无缝的被修改,并且可以选择性同步到 upstream 中

2.3 使用Git Subtree跨仓库同步代码

下边就介绍下使用Git Subtree同步开源仓库的代码,为了介绍方便下边定义一些术语:

  1. 主项目A
  2. 需要同步的开源项目S
2.3.1 在项目父仓库中添加子项目

首先需要把开源项目添加到项目中,在使用 subtree 的时候也需要显式的指定需要添加的子项目。

git subtree add --prefix=<S项目的路径> S项目git地址 xxx分支 --squash

解释:

  • --squash 是将 subtree 的改动合并到一个 commit,不用拉取子项目完整的历史纪录
  • –prefix指定的是克隆后S项目所在的本地目录名,可以是相对路径
  • xxx分支是开源项目S的分支
  • 执行后会产生提交记录,可以使用git statusgit log 查看,只有在执行了push后才会真正提交到主项目A中
2.3.2 更新子项目仓库

在依赖的开源项目S更新了,现在需要把S项目的更新合入到主项目A,执行如下操作:

git subtree pull --prefix=<S项目路径> S项目git地址 xxx分支 --squash
2.3.3 将更改推送到子项目仓库

平时如果要修改S项目的代码,可以直接进行修改,然后提交到主项目A中,但是如果想把对S项目的修改合入到S项目远端仓库,需要执行如下操作:

git subtree push --prefix=<S项目路径> S项目git地址 xxx分支

git subtree push 会将父项目中的提交每一次都进行提交,这会导致对于子项目来说无意义的提交信息,但是 git subtree 并没有提供类似 squash 的方式可以将多次提交合并成一次提交,但是 git subtree 提供了分支的特性,可以在父项目中将修改推送到某一个分支,然后在子项目中使用 squash merge 将修改合并到主干分支。

git subtree push --prefix=<S项目路径> S项目git地址 feature

这会在 foo 的仓库中创建一个叫做 feature 的分支。然后可以从 feature 分支合并回 master 分支。一旦最新的提交都合并到 master 分支,可以通过 pull 来更新

git subtree pull --prefix=<S项目路径> S项目git地址 master --squash

这会在主项目中创建另外一个提交,包括了子项目中所有的修改。这样的方式有一个缺点就是会在父项目中产生一些多余的提交信息。

2.3.4 subtree切换分支

使用 git subtree 加入到父项目的仓库,如果要切换分支,可以直接将 subtree 删掉,然后新加入子项目的分支即可。

git rm <subtree>
git commit
git subtree add --prefix=<subtree> <repository_url> <subtree_branch>

3 Git Upstream

另一种跨远端仓库同步代码的方法就是git upstream,但git upstream只能针对仓库,可以是git submodule添加的子仓库

3.1 什么是upstream?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZkBZKyWC-1611740317116)(en-resource://database/3978:1)]
只要把想要同步的远程仓库设置为本地仓库的 upstream,就可以很方便地进行同步操作了。

3.2 Git Upstream的使用

  • 添加
$ git remote add upstream https://github.com/LambdaSchool/Original-Repo.git
  • 查看
$ git remote -v origin git@github.com:MyName/My-Forked-Repo.git (fetch) origin git@github.com:MyName/My-Forked-Repo.git (push) upstream https://github.com/LambdaSchool/Original-Repo.git (fetch) upstream https://github.com/LambdaSchool/Original-Repo.git (push)
  • 取消upstream
$ git branch --unset-upstream
  • 合并到本地
git fetch  upstream 分支   #拉取远端修改
git merge upstream/分支  --allow-unrelated-histories  #把远端合并到本地仓库
  • 上传到远端
git push origin
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值