zoukankan      html  css  js  c++  java
  • git subtree

    此文已由作者张磊授权网易云社区发布。

    欢迎访问网易云社区,了解更多网易技术产品运营经验。

    前言

    目前对 git 仓库拆分的已有实现之一。这里 git subtree 并不是 subtree merge strategy,这两个不是一个东西。


    准备工作

    1. 首先创建主仓库 subrepo-master,随意提交一次文本,接着拉取到本地

    2. 建立子仓库 subrepo,随意提交一次文本,同时准备多个分支进行任意提交备用。


    操作

    1. 运行 git remote add subtree1 <url> 添加子仓库链接

    2. 添加子仓库 git subtree add --prefix=subtree/subtree1 subtree1 master,这里的 prefix 指向的是本地存放子仓库的目录, subtree1 是第一步添加的远端链接 ,master 是远端分支。添加完成后,就得到了第一个子仓库。

    3. 运行 git status 会发现没有本地修改,接着运行 git log,会发现多了一次提交信息,看起来 git subtree 在添加的时候会自动提交一次,现在可以选择把提交推送到远端。

       commit 6cd935426f68cd670d50a7fb02065af9a0cded19 Merge: fbc33ec afdc5bf     Add 'subtree/subtree1/' from commit 'afdc5bf559beacb08032e23d22a2beaa65d3ca9c'
      
           git-subtree-dir: subtree/subtree1
           git-subtree-mainline: fbc33ec2739057789595c13d2313b87848bf25c0
           git-subtree-split: afdc5bf559beacb08032e23d22a2beaa65d3ca9c
    4. 接着会做一些操作,模拟各种情况,如主仓库子仓库修改推送、子仓库远端拉取合并等。

    5. 主仓库子仓库修改推送到远端

      首先对主仓库子仓库的文件做一些修改并本地提交(记住提交的 message),接着可以直接推送到远端。观察远端主仓库会发现修改顺利提交,subrepo 没有发生改变,这时候就可以体会出一点 subtree 的设计了。如果想推送子仓库,需要使用命令 git subtree push --prefix=subtree/subtree1 subtree1 master。再次观察远端,会发现修改被推送上去了,而且 message 一致。当然你可以选择不推送到 master 分支,随意找一个 git subtree push --prefix=subtree/subtree1 subtree1 master2 也是可以的。观察远端会发现多出一个 master2 分支。

    6. 远端子仓库有修改

      对远端子仓库修改。然后拉取此次提交合并到主仓库。运行此命令拉取即可 git subtree pull --prefix=subtree/subtree1 subtree1 master2,这时候如果有冲突,就需要解决冲突,分别推送主仓库子仓库。然后观察远端仓库,会发现主仓库、子仓库都有了提交以及解决冲突的操作。

    7. 远端子仓库做了大量提交

      希望从远端拉取合并到主仓库 git subtree pull --prefix=subtree/subtree1 subtree1 master2,再运行 git log 然后会发现主仓库的提交日志多了很多,是子仓库的提交日志 + 1 条,如果不希望子仓库污染主仓库的提交日志,可以使用 --squash 这个命令。git subtree pull --prefix=subtree/subtree1 subtree1 master2 --squash,就得到干净了日志了(一次是 squash 整理的提交,一次是合并),但是合并的时候有冲突需要解决。

    8. 本地子仓库合并远端子仓库 branch、tag、commitid

      如果分支没有在本地拉取,则需要先 git fetch subtree1,接着再

       git subtree merge --prefix=subtree/subtree1 subtree1/a
       // or
       git subtree merge --prefix=subtree/subtree1 v2.0
       // or
       git subtree merge --prefix=subtree/subtree1 e1e9aef94c0ce5ede4716d3c1e48cc58c15b7ffe
    9. 本地子仓库改变分支

      可以通过 git subtree pull --prefix=subtree/subtree1 subtree1 b 的方式,但是方式的缺点显而易见,需要手工再次合并代码等等。还有另一种方案,先删去目录,然后重新添加进来。


    技巧

    1. 命令表

       git subtree add   -P <prefix> <commit>
       git subtree add   -P <prefix> <repository> <ref>
       git subtree pull  -P <prefix> <repository> <ref>
       git subtree push  -P <prefix> <repository> <ref>
       git subtree merge -P <prefix> <commit>
       git subtree split -P <prefix> [OPTIONS] [<commit>]
    2. 如果想要历史记录干净一点,可以使用 --squash,可用于 add, merge, push, pull 命令。但是加了 --squash 也有自己的问题,上面已做描述,这个最好一开始就统一使用一种。当然有人也有解决方案 https://stackoverflow.com/questions/9777564/git-subtree-pull-complications


    缺点

    1. 合并策略的学习成本

    2. 返回历史版本稍显复杂

    3. 不要混合提交主仓库、子仓库代码

    4. 将子仓库推送到远端很慢,相当于对主仓库下某个子仓库的目录的提交记录进行分割,以找出子仓库的修改,这个过程有点慢,如果推送周期比较长倒是可以尝试。

    5. 需要添加多个远端,子仓库和远端没有地方存储映射关系。由命令 git subtree pull --prefix=subtree/subtree1 subtree1 master2 可以看出来,可以推送子仓库的代码到任意能推送的地方。

    6. 改子仓库的分支略坑


    优点

    1. 拷贝主仓库后,可以直接使用

    2. 使用者可以不关注子树依赖,对使用者无感知,不需要子仓库权限

    3. 子树不像子模块会添加多余的文件,对仓库无污染

    4. 对子仓库的同步可交由单独的维护者


    参考

    1. https://github.com/git/git/blob/master/contrib/subtree/git-subtree.txt

    2. https://developer.atlassian.com/blog/2015/05/the-power-of-git-subtree/

    3. https://www.atlassian.com/blog/git/alternatives-to-git-submodule-git-subtree

    4. https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec


    免费体验云安全(易盾)内容安全、验证码等服务

    更多网易技术、产品、运营经验分享请点击


    相关文章:
    【推荐】 聊聊空状态设计
    【推荐】 大数据在政府中的应用案例

  • 相关阅读:
    Spring事务管理
    Java GC算法
    内连接,左连接,右连接
    ThreadLocal相关
    @Autowired 与 @Resource的区别
    spring注解
    BZOJ 1040 ZJOI 2008 骑士 树形DP
    HDU 5575 Discover Water Tank 并查集 树形DP
    BZOJ 3571 画框 KM算法 最小乘积最大权匹配
    ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法
  • 原文地址:https://www.cnblogs.com/163yun/p/9920852.html
Copyright © 2011-2022 走看看