Автономная синхронизация локально-центральных репозиториев git - PullRequest
0 голосов
/ 24 марта 2019

У нас есть две разные команды, каждая в своем местоположении, работающая с git, у каждого местоположения есть репозиторий ссылок.Каждое местоположение имеет доступ к корпоративной сети, но две сети не могут быть напрямую связаны (поверьте, мы спросили): мы можем только обмениваться файлами.Мы хотели бы иметь возможность регулярно синхронизировать два местоположения, чтобы можно было делиться работой через соответствующие репозитории.

Требования:

  • Обмены должны быть разрешены в любом направлении.
  • Нам нужно иметь возможность работать над некоторыми ветвями одновременно с обеих сторон или, по крайней мере, восстанавливаться в случаях, когда это произошло, даже если мы ожидаем, что большую часть времени будем работать над отдельными ветвями.Это подразумевает, что для обработки расходящихся работ может потребоваться шаг интеграции.
  • Большая часть отслеживания должна выполняться автоматически, так что ручное вмешательство и риск ошибок манипулирования из-за этого сводятся к минимуму (не то, что они будут фатальными,но лучше всего не указывать пальцем: доверие ограничено).В частности, один пример движущегося тега, используемый на странице руководства git-bundle, вызывает смех, поскольку он не будет масштабироваться даже до ограниченного числа ветвей (у нас есть десятки).
  • Справочные репозитории могут быть толькоманипулировать с помощью удаленного push / pull и, при необходимости, облегчить административные операции, потому что они находятся под контролем IT, и потому что мы хотим, чтобы они были всегда согласованными, то есть сначала выполняется интеграция, и только затем вместе публикуются изменения с другой стороны.с интеграцией, в локальный репозиторий.
  • Мы не можем отправлять весь репозиторий (даже tar-gzipped) каждый раз: он не только немного большой, но и все отправленные подряд пакеты хранятся в записях.потому что это является частью договорных обязательств, и наличие N копий хранилища быстро станет неустойчивым.
  • Вся необходимая информация должна храниться в локальном ссылочном хранилище, чтобы любой разработчик мог выполнитьсинхронизациишаги, не зависящие от информации, хранящейся в локальном хранилище (ях) конкретного разработчика.
  • Работайте с git, а не против него, по крайней мере, в той степени, в которой это возможно.Чем страннее рабочий процесс, тем более вероятно, что он прервется из-за изменения в git или другого непредвиденного условия.

Необязательные требования:

  • Обработка более чемдва отключенных сайта.Два уже будут достаточно сложными.
  • Ночная обработка.Обмены будут запускаться и обрабатываться вручную.
  • Ограниченное количество или сложность команд.Если необходимо много сложных команд, так и быть, мы всегда можем скрыть эту сложность в скрипте.
  • Пересечение автономных синхронизаций.Это всегда означает проблемы, как с потоками.Следовательно, мы можем предположить, что операции автономной синхронизации полностью упорядочены, независимо от их направления, по очереди при необходимости.
  • Детали управления филиалами и т. Д. Это наш внутренний бизнес.

1 Ответ

1 голос
/ 24 марта 2019

Решение, которое я имею до сих пор, состоит в том, чтобы использовать команду git bundle, полагаясь на удаленные ссылки для отслеживания того, что уже есть в другом местоположении, с некоторыми необходимыми шагами, которые я придумал, для переноса этих удаленных ссылок через push / pull , Пусть наше местоположение будет называться site-a, а удаленное местоположение будет называться site-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. В этот момент выборка сообщает, какие удаленные ветви сайта-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 merge операции требуют не обнаженного хранилища. Шаг 3 необходим для того, чтобы «припарковать» HEAD подальше от любой ветви, в противном случае шаг 4 потерпит неудачу, если и когда он попытается напрямую обновить ветку, на которую указывает HEAD. Шаг 4 необходим (он не извлекает никакой фиксации), поскольку он установит все необходимые ссылки, поскольку удаленный пакет может не обязательно содержать все ветви (он пропускает те, где он не предоставляет обновления), в то время как в конце мы собираемся обрезать ветки от источника на основе наших собственных ветвей, поэтому мы хотим начать со всех ветвей, которые имеет источник; указание refspecs из этого шага в качестве опции -c для исходного клона вместо этого не работает. Шаг 5 необходим, чтобы git знал, как обновить ссылки в refs/remotes/site-b/* на шаге 6.

  • Обновление удаленных ссылок отслеживания, когда удаленное местоположение подтвердило, что им удалось получить содержимое отправленного им пакета:

    Это делается, выполнив шаги из «Интеграции пакета из удаленного местоположения», за исключением того, что вы берете отправленный пакет, как будто он приходит из удаленного местоположения; очевидно, в этом случае не требуется никакой работы по интеграции, так как филиалы нашего местоположения обязательно обновлены информацией из пакета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...