Являются ли параллельные git толками всегда безопасными, если второй толчок только вперед-вперед от первого нажатия?

Я хочу автоматически нажимать коммиты в методе post-receive из центрального репо в нашей локальной сети на другое центральное репо в облаке. Локальная репо создается с помощью git clone --mirror [email protected]:/path/to/repo или эквивалентных команд.

Поскольку файлы, которые будут совершены, будут большими относительно нашей полосы пропускания вверх, вполне возможно, что это может произойти:

  • Алиса инициирует нажатие на репозиторий LAN.
  • Билл вытаскивает из репозитория LAN во время запуска крюка после приема.
    • Локальная репо находится в середине перехода к облачному репо.
    • Это также означает, что местное репо Билла содержит коммиты, которые Алиса нажала. Подтверждено путем тестирования.
  • Билл инициирует нажатие на ретрансляцию локальной сети.
    • Билл-нажим - это быстрый переход от Alice push, поэтому ретрансляция LAN примет его.

Когда выполняется перехват post-receive для репо-сервера LAN, начнется второе нажатие от ретрансляции локальной сети до облачного репо, и оба будут выполняться одновременно.

Я не беспокоюсь о git объектах. Наихудший сценарий заключается в том, что обе кнопки загружают все объекты с помощью нажатия Alice, но это не имеет значения, насколько я понимаю внутренние элементы git.

Меня беспокоят ссылки. Предположим, что Алиса нажала, используя гораздо более медленное соединение, так что сначала нажимать Билл заканчивается. Предположим, что потеря пакетов или что-то еще вызывает нажатие на крючок из репозитория LAN в облако Билла, чтобы завершить до того, LAN-репо на облако Алисы. Если и Алиса, и Билл нажимают главную ветку, и сначала нажимает Билл, Каким будет мастер ref на облачном репо? Я хочу, чтобы это был Bill HEAD, так как это более поздний толчок, но я обеспокоен тем, что это будет Alice HEAD.

Дальнейшие разъяснения:

Я понимаю, что Алиса выталкивает из своей машины в локальную репо, если она не сработает, когда Билл отодвинется от своей машины до локального репо. В этом случае крюк post-receive LAN repo не будет выполняться. Кроме того, предположите, что никто не будет делать силовые нажатия, поэтому , если крюк post-receive работает в репо LAN, все изменения ref быстро переходят.

Ответ 1

Если предикат Билла заканчивается, первый щелчок Алисы завершится неудачно, потому что перед обновлением refs git убедитесь, что ref для репо остается тем же, что и раньше. В этом случае этого не будет. Алиса в конечном итоге увидит сообщение об ошибке и должна решить проблемы. То же самое касается Билла в обратном случае. Таким образом, в вашем post-receive hook вы должны убедиться, что исходные и новые ссылки для репо теперь разные. Если нет, то не отказывайтесь от нового репо вообще, чтобы сохранить какую-то работу.

Я все еще вижу проблему в вашем сценарии, хотя и с толчком к облаку. У вас может быть ТОЧНАЯ проблема, при этом крючок нажимает два действительных refs до места облака. За исключением теперь вы не знаете, если вам нужно нажать на репо в script, если он не сработает в первый раз, потому что вы не будете знать, был ли неудачный реф был старше или новее, чем тот, который был нажат... особенно, если они weren ' t простые быстрые переходы, которые могут время от времени возникать. Если вы просто вынудили толчок, независимо от того, что у него получилось бы, облако будет иметь OLD ref, пока другой крюк не подтолкнет что-то еще позже. В случае с Алисой он бы объединил изменения с восходящего или любого другого решения, но script, вероятно, не должен иметь такой возможности принятия решений.

В этом случае вы можете сделать магию script в текущем репо, чтобы определить временные метки и т.д. и только нажать, если есть быстрая перемотка вперед, но это кажется беспорядочным, и, скорее всего, требуется слияние так или иначе. Я думаю, что лучшим решением, чем использование крюка после приема, является использование задачи cron или schedule каждые пять минут (или, как бы часто вы этого не хотите), которая просто запускает git pull на главной ветки вашего удаленного зеркала. Если у вас нет доступа к этому репо, вы можете сделать принудительное нажатие из своего репо-сервера с помощью задания cron. Я думаю, что это безопаснее, чем крючок и менее сложный. Это обеспечит вам, что ветка на резервном облаке всегда находится в правильном месте каждые несколько минут и не рискует выталкивать старый реф и никогда не получать самую новую, пока не будет другого нажатия от пользователя, как это делает hook.

Ответ 2

Git 2.4+ (Q2 2015) представит атомные нажатия, что должно облегчить работу сервера для управления порядком толкания.
См. Работу, выполненную Стефан Беллер (stefanbeller):

  • совершить ad35eca t5543-atomic-push.sh: добавить базовые тесты для атомных нажатий

Это добавляет тесты для атомарного push-опции.
Первые четыре теста проверяют, работает ли атомная опция в хороших условиях, и последние три патчи проверяют, не блокирует ли атомный параметр любые изменения, если только один ref не может быть обновлен.

  • commit d0e8e09 push.c: добавить аргумент --atomic

    --[no-]atomic
    

Используйте атомную транзакцию на удаленной стороне, если она доступна.
Все исправления обновляются, или при ошибке, никакие ссылки не обновляются.
Если сервер не поддерживает атомарные нажатия, то нажатие не будет выполнено.

  • commit 4ff17f1: send-pack.c: добавить --atomic аргумент командной строки

Это добавляет поддержку send-pack для согласования и использования атомных нажатий если сервер поддерживает его. Атомные нажатия активируются новой командой флаг линии --atomic.

  • commit 1b70fe5: receive-pack.c: согласовать поддержку атомарного push

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

   atomic
   ------

Если сервер отправляет возможность "atomic", он способен принимать атомарные нажатия.
Если push-клиент запрашивает эту возможность, сервер обновит ref в одной транзакции атома.
Либо все ссылки обновляются, либо нет.