使用git子树合并,同时也合并所有合并子树的所有分支

ant*_*ony 8 git merge subtree redmine

我想使用一个流行的开源问题跟踪器(Redmine)来提供git集成.不幸的是,跟踪器中的每个项目只能与一个git仓库相关联.在跟踪器中创建多个项目不是我理想的设置.

考虑到这一点,我试图使用git子树合并(在这里解释,这里).我已经创建了一个"伞形"仓库,它已合并到我正在使用的众多其他仓库中.

遗憾的是,给出的示例仅引入每个子树的主分支.由于我在每个子树的多个分支中进行开发,我需要学习如何使用这个伞形回购反映每个子树的每个分支.

这可能吗?

额外信用:如果2个子树每个都有一个同名的分支怎么办?

Chr*_*sen 7

对于我们这些不熟悉Redmine的人,请扩展您的描述以包含以下问题的答案:跟踪器需要什么样的访问存储库?是否需要自己提交?或者,它是否只需要某些类型的读访问权限(可能是为了验证提交哈希值和扫描提交关键字的日志)?

如果您的跟踪器只需要读访问权限,则可能根本不需要任何子树合并.在单个存储库中进行多次初始提交(允许多个独立历史记录)是完全可以接受的.Git项目本身为一些"额外"(man,html,todo)执行此操作,这些"额外"(man,html,todo)与源代码(maint,master,next,pu)的主要分支集合一起发布.出于您的目的,为每个子存储库设置远程数据并将其分支提示提取到聚合存储库中可能就足够了.也许自动"远程跟踪分支"就足够了,或者你需要采取额外的步骤来创建(和更新)基于远程跟踪分支的本地分支.

您描述的子树合并方案在源存储库中的分支不相关或仅半相关的一般情况下可能没有意义.但是,如果所有源存储库共享一组分支,其中每个分支具有在所有存储库中相同的给定目的,则可能有意义地将它们合并到一种超级存储库中.

但有趣的问题不是"如果两个存储库具有相同名称的分支怎么办?",但是"如何处理存储库缺少共享的'全局'集合的分支?".

如果所有子存储库都具有相同的分支集合,那么您只需执行使用master执行的操作,但对每个分支执行一次.当存储库中缺少特定分支时,问题就出现了.你可以替换它的主人,但这可能并不总是正确的答案.这取决于您首先将存储库聚合在一起的原因以及您希望在超级存储库中该分支的子树中"看到"的内容.

如果子存储库没有密切相关,那么我真的怀疑这个子树方法的合理性.对于不相关的存储库来说,这种方法感觉就像是"反对谷物".它可能仍然可能,但我怀疑有任何工具可以提供帮助,你需要花一些时间来规划角落案例.

如果您最终坚持使用子树合并,则可能会查看第三方git subtree命令.它可能有助于保持无数的存储库同步.


收集分支,没有合并

如果Redmine指定了--mirrorclone,则暗示它需要本地分支,并且可能无法直接读取"远程跟踪分支",因此您可能需要创建和更新某些本地分支.

从"远程跟踪分支"更新的本地分支机构
  • 初始设置

    mkdir $COLLECTION_REPO && cd $COLLECTION_REPO &&
    git init
    git remote add alpha <url/path-to-alpha-repo>
    git remote add bravo <url/path-to-bravo-repo>
    git remote add charlie <url/path-to-charlie-repo>
    for r in $(git remote); do
        git config --add remote.$r.fetch \
          "$(git config remote.$r.fetch | sed -e 's.heads.tags.;s.remotes.tags/all.')"
        git config remote.$r.tagopt --no-tags
    done
    
    Run Code Online (Sandbox Code Playgroud)
  • 定期更新

    git remote update
    git for-each-ref --shell --format \
      'git branch --force --track -l all/%(refname:short) %(refname:short)' refs/remotes \
      | sh
    
    Run Code Online (Sandbox Code Playgroud)
直接收到分支提示的本地分支机构
  • 初始设置

    mkdir $COLLECTION_REPO && cd $COLLECTION_REPO &&
    git init
    git remote add alpha <url/path-to-alpha-repo>
    git remote add bravo <url/path-to-bravo-repo>
    git remote add charlie <url/path-to-charlie-repo>
    for r in $(git remote); do
        git config remote.$r.fetch \
          "$(git config remote.$r.fetch | sed -e 's.remotes.heads/all.')"
        git config --add remote.$r.fetch \
          "$(git config remote.$r.fetch | sed -e 's.heads.tags.g')"
        git config remote.$r.tagopt --no-tags
    done
    
    Run Code Online (Sandbox Code Playgroud)
  • 定期更新

    git remote update
    
    Run Code Online (Sandbox Code Playgroud)

两种方法都最终收集了分支refs/heads/all/<remote-name>/<branch-name-on-remote>,但第一种方法也有一组重复的引用refs/remotes/<remote-name>/<branch-name-on-remote>.第一个使用普通的fetch refspec,用于git branch将'remote tracking branches'(refs/remotes/…)复制到普通的本地分支(refs/heads/all/…)中.第二个使用自定义refspec将获取的引用直接存储到目标引用层次结构中.

由于更新被盲目地提取到这个组合存储库的方式,没有人应该尝试直接使用它:没有直接在其分支上提交,不从外部推送.如果有人要在本地提交或推送到其中一个分支,则在下一次更新完成后,这些提交将被清除.

如果Redmine可以处理裸存储库,我建议使用一个.使用git init --bare和以.git结尾的repo名称.也git config core.logAllRefUpdates true可能是一个好主意(因为在裸存储库中默认为false).

除了all/名称空间中的前缀之外,此方法与完整--mirror克隆之间的另一个区别是refs在外部refs/heads并且refs/tags不会被收集.大多数其他常见引用被认为是存储库的"本地"(这就是为什么它们不被正常克隆复制的原因).其他一些refs是'远程跟踪分支'(refs/remotes),一些'bisect'记录保持(refs/bisect),git filter-branch'原始'ref备份(refs/original),等等.可能这些其他事情对Redmine来说都不重要.如果是,他们也可以包含额外的refspecs.

创建额外的初始提交

要安排具有新初始提交的分支,请参阅如何创建没有祖先的新分支下的GitTips页面.其中两个配方涉及另一个存储库,在完成通常的init/add/commit步骤后,您可以从中推送或获取一个分支(正是上述配方以自动方式执行的操作).