Skip to content

zyestin/MainRepoDemo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 

Repository files navigation

多个仓库 如何 共享某一模块/代码/仓库

How do multiple repos share dir/code/module/repo, some solutions as below:

  • git subtree
    一般不可忍受:子仓库的记录,一旦被主仓库拉取,子仓历史commit记录全都进入主仓;未来在本地主仓更改了子仓代码,在主仓提交后,然后同步到子仓远端,这样的正常操作,主仓的commit其实融合了子仓的代码改动的,显得混乱。而submodule就很纯粹,子仓的更新commit永远在子仓, 主仓仅仅是指定选用子仓的某个commit拉取过来用而已,父子联系上仅仅一个commit号即可。
  • git fetch && checkout方式 merge 子仓库代码 到 主仓库指定的目录
    很强不可忍受点:与手动从子仓库拷贝代码到主仓库方式一样,这些diff,又会出现在主仓库 又需要重新在主仓库commit。。。
  • soft link (电脑上建立目录软链)
    较强不可忍受点:.gitignore是忽略了主仓库中的 子仓库的所有代码的,相当于远端代码库 缺了这一块,然而,连这块的关联信息 该如何解决? 一般不可忍受点:在VSC主仓库修改了子仓库代码,(可以忍受:需要去真正的子仓库去提交代码),就必然会多开一个子仓库窗口 进行git操作。
  • git submodule
    需要注意地方:在主仓库中修改子仓库,通过命令先提交子仓库代码,再提交主仓库代码。认为这是顺理成章的,因为子仓库代码改动,本该独立更新

    越来越觉得,这是软链的增强版

    1. 主仓库远端,缺失的子仓库这一块,但.gitmodule能表示与具体子仓库的关联关系
    2. 在VSC主仓库修改了子仓库代码,可以在主仓库,打包几个命令,做到在主仓库直接维护子仓库。
  • multiple workspace
    暂未实践

dir structure && description

├── README.md                 当前文件
└── app                       应用代码目录
    ├── base_shared           基础设施代码 **与其它项目可共享的**
    │   ├── components
    │   │   └── list
    │   │       └── base.js
    │   └── utils
    │       └── theme
    │           └── index.js
    ├── common                 常用组件、工具代码  非共享的、MainRepoDemo才会用到的
    │   ├── components
    │   │   └── navigationBar
    │   │       └── index.js
    │   └── utils
    │       └── time
    │           └── index.js
    └── modules                模块集合,存放MainRepoDemo用到的各业务模块 
        ├── graphic_shared     graphic模块 **共享自(来自于)其他项目**
        └── home
            └── index.js

方式1: git subtree 合并某仓库 的指定目录 到 另一仓库的指定目录

尝试 指定子仓库的指定目录

  • 添加 GraphicRepoDemo 仓库作为远程仓库,以便后续使用它的内容
git remote add graphicproject-remote git@github.com:zyestin/GraphicRepoDemo.git

sourceTree效果图 image

  • 使用 Git subtree 将 "GraphicRepoDemo" 的 "app/modules/graphic_shared" 目录合并到 "MainRepoDemo" 仓库的相同路径下。运行以下命令:
git subtree add --prefix=app/modules/graphic_shared graphicproject-remote master --squash

但结果却是 把GraphicRepoDemo全部代码 合并到了 MainRepoDemo的"app/modules/graphic_shared" 目录下。 确实做到了commit信息继续,而不产生新的commit信息 image

既然希望commit信息继续保留(范围是整个GraphicRepoDemo仓库) 而不会产生新的commit,又希望指定仓库中的一个子目录"app/modules/graphic_shared"(范围并不是整个仓库)来merge,看来本该就是做不到了,不管用不用subtree

于是,需要将graphic_shared单独作为一个仓库,供MainRepoDemoGraphicRepoDemo用subtree方式享用,即可~

尝试 将子目录抽出来作为单独子仓库 去作为整体共享

  • GraphicRepoDemo下"app/modules/graphic_shared"内的文件转移到 GraphicRepo

  • 删掉MainRepoDemoGraphicRepoDemo下"app/modules/graphic_shared"

MainRepoDemo试一试

  • 移除MainRepoDemo之前的subtree
git remote remove graphicproject-remote
  • MainRepoDemo添加子仓库
git remote add graphicrepo git@github.com:zyestin/GraphicRepo.git
git subtree add --prefix=app/modules/graphic_shared graphicrepo main --squash

这样,

  • 在父仓库MainRepoDemo中更新了子仓库中的内容,同步到子仓库
//先提交父仓库
git add
git commit

//再提交到子仓库
git subtree push --prefix=app/modules/graphic_shared graphicrepo main          
git push using:  graphicrepo main
Enumerating objects: 55, done.
Counting objects: 100% (55/55), done.
Delta compression using up to 8 threads
Compressing objects: 100% (42/42), done.
Writing objects: 100% (50/50), 7.40 KiB | 2.47 MiB/s, done.
Total 50 (delta 10), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (10/10), completed with 1 local object.
To github.com:zyestin/GraphicRepo.git
   0cb8da2..ff099bb  ff099bbbc7ac3939ec0073f1bdc302fa4f5bfc26 -> main

可以看到子仓库,有许多待拉取的,吓人 image

注:应该是某种操作导致,正常使用不会这样(吓人情况 主仓一堆commit记录跑到子仓去了)。 正常情况下,在本地主仓更改了子仓,提交主仓后,若同步到子仓,仅仅只是从主仓中挑出属于子仓代码 进行合并提交到子仓远端。

  • 子仓库 pull 可以看到,在父仓库对子仓库做的修改,已经同步过来了
image

可见,虽然在父仓库对子仓库做的修改后 可以通过subtree push将更改同步到子仓库,但是 子仓库的commit信息,竟然被污染了!!!

方式2:git fetch && checkout方式merge

执行如下命令

git fetch graphicproject-remote
git checkout graphicproject-remote/main -- app/modules/graphic_shared

类似于手动 从GraphicRepoDemo把"app/modules/graphic_shared"拷贝,黏贴到MainRepoDemo的该目录

方式3:软链

在本地MainRepoDemo的"app/modules/graphic_shared",通过软链指向GraphicRepoDemo的"app/modules/graphic_shared"

注意:.gitignore中需要忽略"app/modules/graphic_shared",防止提交了这个软链空壳文件上去

方式4:git submodule

GraphicRepoDemo试一试 往里面关联 一个新的子仓库Graphic2Repo

GraphicRepoDemo的"app/modules/graphic_shared"目录,拉取子仓库Graphic2Repo代码

pwd                                 
/Users/yestin/Desktop/gitfiles/RepoShare/GraphicRepoDemo

git submodule add git@github.com:zyestin/Graphic2Repo.git app/modules/graphic_shared
image `git submodule add`这个关联操作,只会新增两个改动`.gitmodules`、`app/modules/graphic_shared` (而不会将`graphic_shared`内部的各个文件都作为新增改动)

实际的app/modules/graphic_shared目录下的文件,是与 子仓库Graphic2Repo代码 一致的 image

子仓库Graphic2Repo代码更新,更新 父仓库GraphicRepoDemo的"app/modules/graphic_shared"目录代码

git submodule update --remote app/modules/graphic_shared
Submodule path 'app/modules/graphic_shared': checked out '68e524d1b15e3d678a094e83e6a02d3cb8116fc8'

git status变化:仅app/modules/graphic_sharedcommit id变化了 image

实际代码变化:父仓库app/modules/graphic_shared内代码与子仓库一致了 image

在父仓库更改子仓库代码,将改动更新到子仓库远端

  • 更改代码,保存
    • 更改前
    image * 更改后 image

发现,此时仅子仓库的git status有变化。

对比subtree 就会发现在主仓库也发现代码变更信息,那么用subtree就明显不合适了 image

  • commit
cd app/modules/graphic_shared
git add .
git commit -m "test: 在父仓库更改子仓库代码,更新远端子仓库代码"

commit后,父仓库下git status就有变化了,app/modules/graphic_sharedcommit id变化了 image

  • push 子仓库的改动同步到远端子仓库
    • 通过命令
      cd app/modules/graphic_shared
      //... add commit ... 可直接在VSC操作
      git push origin HEAD:graphic2-remote       //可以指定 main 或别的 远程分支
      Enumerating objects: 10, done.
      Counting objects: 100% (10/10), done.
      Delta compression using up to 8 threads
      Compressing objects: 100% (4/4), done.
      Writing objects: 100% (6/6), 629 bytes | 629.00 KiB/s, done.
      Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
      remote: Resolving deltas: 100% (2/2), completed with 1 local object.
      To github.com:zyestin/Graphic2Repo.git
         16b612c..0833e03  HEAD -> graphic2-remote
      
      下图可见,子仓库的git log非常纯粹,commit 都是子仓库代码改动信息 image
    • 通过VSC也可以push子仓库代码 image

      VSC push后,确实子仓库远端ok了 image

一般git push前还是先git pull一次,以免他人push了,就会报如下错误
报这个错的话,就执行git config pull.rebase false,然后再pull

git pull origin graphic2-remote
From github.com:zyestin/Graphic2Repo
 * branch            graphic2-remote -> FETCH_HEAD
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint: 
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.

多人协作 在主仓拉取子仓代码

  • 对于首次,直接操作submodule update ? 不,首次需要先操作git submodule update --init
    他人首次拉取GraphicRepoDemo后,会发现app/modules/graphic_shared目录下的代码是空的,看来需要额外的操作去同步这块代码
git submodule update --init --recursive                15:30:27
Submodule 'app/modules/graphic_shared' (git@github.com:zyestin/Graphic2Repo.git) registered for path 'app/modules/graphic_shared'
Cloning into '/Users/yestin/Desktop/gitfiles/RepoShare/GraphicRepoDemo2/app/modules/graphic_shared'...
Submodule path 'app/modules/graphic_shared': checked out '6ee3837c117a0f9b2696f3f0b3099ff21333b235'

操作完git submodule update --init --recursive 发现app/modules/graphic_shared目录下的代码已经同步过来了 image

直接操作,会出现什么问题呢?会有如下提示

git submodule update --remote app/modules/graphic_shared
Submodule path 'app/modules/graphic_shared' not initialized
Maybe you want to use 'update --init'?
  • 非首次,操作git submodule update --remote app/modules/graphic_shared
    • 当一个同事更新了 子仓库Graphic2Repo 其他同事如何感知呢?
      使用sourcetree的同事,在主仓库是感知不到有未pull的commit的,(VSC本来就不支持提示有N个待pull的commit) 此时可以打开VSC的commit graph可视化窗口,能看出是否有待pull的commit,如下图
    image * 执行 在主仓库拉取子仓库代码
git submodule update --remote app/modules/graphic_shared
Submodule path 'app/modules/graphic_shared': checked out '3ab3f32779995d68522878d563dfb63bfbd5f2ab'

本以为 .gitmodule文件中记录了 path = app/modules/graphic_shared,以为直接执行git submodule update,不用指定路径了, 但依然需要执行完整的git submodule update --remote app/modules/graphic_shared

多人协作 子仓库多人次修改和提交

  • 没有冲突时
    在主仓改子仓,commit但不push;
    在子仓改,commit且push
image 然后,在主仓先pull后push,即点击`Sync Changes` image 会报错一次,如下,执行一次`git config pull.rebase false`就好了,以后`Sync Changes`将不再被中断,直接会进行merge ``` hint: You have divergent branches and need to specify how to reconcile them. ... ``` VSC 通过`Sync Changes`执行 pull && push后,本地、远程子仓库更新成功 image
  • 有冲突时 VSC操作Sync Changes后,正常走熟悉的merge流程,标记出了冲突代码
image 然后,修复掉冲突代码,操作 `stage`、`commit`、`Sync Changes`就可以了

参考

commit: 父仓库直接提交父子仓库目录里的变动。若修改了子仓库的文件,则需要执行 subtree push

四个方案个人认为的排序是subtree = submodule > dll > npm

  • GPT 对比 subtree与submodule

image

About

多个仓库共享某一模块/代码/仓库 各方案实操对比

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published