2

我们有两个不同的团队,每个团队都在自己的位置,使用 git,每个位置都有一个参考存储库。每个位置都可以访问企业网络,但两个网络不能直接连接(相信我,我们问过):我们只能交换文件。我们希望能够定期同步这两个位置,以便可以通过各自的参考存储库共享工作。

要求:

  • 必须允许双向交换。
  • 我们需要能够同时在双方的某些分支上工作,或者至少从发生这种情况的情况中恢复,即使我们希望大部分时间都在单独的分支上工作。这意味着可能需要一个集成步骤来处理不同的工作。
  • 大多数跟踪必须自动发生,以便最大限度地减少人工干预和操作错误的风险(并不是说它们会致命,但最好避免相互指责:信任是有限的)。特别是,在 git-bundle 手册页中使用的单个移动标签示例是可笑的,因为它甚至无法扩展到有限数量的分支(我们有几十个)。
  • 参考存储库只能通过远程推/拉和必要的轻管理操作进行操作,这既是因为它们在 IT 控制之下,也是因为我们希望它们始终保持一致,即首先完成集成,然后才进行更改另一方与集成一起在本地参考存储库上发布。
  • 我们不能每次都发送整个存储库(甚至是 tar-gzip):它不仅本身有点大,而且所有连续发送的包都保存在记录中,因为这是合同承诺的一部分,并且在其中有 N 个存储库副本很快就会变得不可持续。
  • 所有必要的信息都必须存储在本地参考存储库中,以便任何开发人员都可以执行同步步骤,而无需依赖存储在特定开发人员的本地存储库中的信息。
  • 使用 git,而不是反对它,至少尽可能多地这样做。工作流程越怪异,就越有可能因为 git 的变化或其他意外情况而中断。

非要求:

  • 处理两个以上断开连接的站点。两个已经足够具有挑战性了。
  • 每晚处理。交换将被手动触发和处理。
  • 命令的数量或复杂性有限。如果需要许多复杂的命令,就这样吧,我们总是可以在脚本中隐藏这种复杂性。
  • 跨越离线同步。这总是意味着麻烦,就像流一样。因此,我们可以假设离线同步操作是完全有序的,无论它们的方向如何,必要时轮流进行。
  • 分公司管理细节等。那是我们内部的业务。
4

1 回答 1

1

到目前为止,我的解决方案是使用git bundle命令,依靠远程引用来跟踪其他位置已经有什么,我想出了一些涉及的步骤来通过推/拉来携带这些远程引用。让我们的位置称为站点-a,远程位置称为站点-b。

  • 生成要发送到远程位置的捆绑包:

    1. ~/work$> git clone $LOCAL_REF_URL --mirror bundler
    2. ~/work$> cd bundler
    3. ~/work/bundler$> git bundle create ../bundle-site-a-$(date +%Y-%m-%d) --branches --tags --not --remotes=site-b

    捆绑器工作存储库现在可能会被丢弃。

  • 从远程位置集成捆绑包:

    1. ~/work$> git clone -n $LOCAL_REF_URL bundle-integration
    2. ~/work$> cd bundle-integration
    3. ~/work/bundle-integration$> git checkout --detach
    4. ~/work/bundle-integration$> git fetch origin 'refs/heads/*:refs/heads/*' 'refs/remotes/site-b/*:refs/remotes/site-b/*'
    5. ~/work/bundle-integration$> git remote add site-b ../bundle-site-b
    6. ~/work/bundle-integration$> git fetch --tags site-b 'refs/heads/*'
    7. 此时,fetch 会告诉哪些远程站点 b 分支已使用捆绑包中的信息进行了更新,因此在此处插入必要的工作以集成在我们位置具有相应分支的分支;首先是git fetch . 'refs/remotes/site-b/*:refs/heads/*'快进那些可以一举成名的事情,然后git checkout $BRANCH && git merge site-b/$BRANCH是其他人:历史的任何一方都无法改写。还要删除捆绑包考虑但不再包含的分支。
    8. 如果git push --tags origin 'refs/heads/*:refs/heads/*' 'refs/remotes/site-b/*:refs/remotes/site-b/*' --prune完全成功,则返回;我们完了
    9. ~/work/bundle-integration$> git fetch origin(一个普通的)
    10. 考虑在您忙于执行上述步骤时在您所在位置完成的工作;仍然必须通过合并来完成(尽管使用更常见的git checkout $BRANCH && git merge origin/$BRANCH习惯用法),除了您自己的合并工作,如果您愿意,可以重新设置
    11. 转到 8

    现在可以丢弃捆绑集成工作存储库。

    注意:步骤 1 不能只是一个镜像克隆,因为 --mirror 不仅假定 --bare,它还强制它,这与稍后执行集成的需要不兼容:即使是微不足道的(快进)git 合并操作也需要非裸存储库。步骤 3 是必要的,以便HEAD从任何分支“停放”,否则如果尝试直接更新分支时,步骤 4 将失败HEAD是指向。第 4 步是必要的(它不获取任何提交),因为它将设置所有必要的引用,因为远程包可能不一定包含所有分支(它省略了不提供更新的分支),而最后我们要根据我们自己的分支从原点修剪分支,所以我们要从原点的所有分支开始;将此步骤中的 refspecs 指定为初始克隆的 -c 选项似乎不起作用。第 5 步是必要的,因此 git 知道要更新refs/remotes/site-b/*第 6 步中的引用。

  • 当远程位置确认能够获取发送给他们的捆绑内容时,更新远程跟踪引用:

    这是按照“从远程位置集成捆绑包”中的步骤完成的,除了将发送的捆绑包视为来自远程位置;显然,在这种情况下不需要集成工作,因为我们所在位置的分支必须与捆绑包中的信息保持同步。

于 2019-03-23T23:52:10.503 回答