Возможны ли параллельные операции с репозиториями Git?

Есть два сценария, которые меня интересуют.

  • Репозиторий разделяется, и два пользователя хотят одновременно вносить изменения в него.
  • Я хочу запланировать ночной или еженедельный "gc" с помощью задания cron. Он запускается, и кто-то хочет нажать или клонировать во время операции.

Есть ли риск коррупции в любом из этих сценариев?

Ответ 1

Git позволяет выполнять параллельные операции с помощью пессимистичного Concurrency элемента управления.

При необходимости git создает специальные файлы для блокировки.

В частности, каждый раз, когда индекс модифицируется операцией, git создает файл с именем index.lock в каталоге .git для блокировки общего ресурса. git создает при необходимости другие файлы блокировки: например, файл .keep создается во время операций Git index-pack.

В общем, вы не должны беспокоиться о параллельных операциях с git: он тщательно разработан для их поддержки.

Кто-то может сказать, что не стоит беспокоиться о выполнении gc с заданием cron, так как git сам запускает gc время от времени. Даже если это правда, man page рекомендует:

Users are encouraged to run this task on a regular basis 
within each repository to maintain good disk space utilization
and good operating performance.

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

Ответ 2

В общем, " git gc " может удалять объекты, которые использует другой параллельный процесс, но не создал ссылку.
У Git 2.12 (1 квартал 2017 года) есть больше об этом.

См. Коммит f1350d0 (15 ноября 2016 г.) Мэтта Маккатчена (mattmccutchen).
(Объединено Junio C Hamano - gitster - в коммите 979b82f, 10 января 2017 г.)

И посмотрите комментарий Джеффа Кинга:

Современные версии git делают две вещи, чтобы помочь с этим:

  • любой объект, на который ссылается "недавний" объект (в течение 2 недель), также считается недавним. Поэтому, если вы создаете новый объект коммита, который указывает на дерево, даже до того, как вы ссылаетесь на коммит, это дерево защищено

  • когда запись объекта оптимизирована, потому что у нас уже есть объект, git обновит mtime в файле (свободный объект или файл пакета), чтобы освежить его

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

Если у вас есть долгосрочные данные (например, временный индексный файл, который может буквально сидеть без дела несколько дней или недель), я думаю, что это потенциальная проблема. И решение, вероятно, заключается в том, чтобы как-то использовать ссылки для указания на ваши объекты.
Если вас беспокоит кратковременная операция, когда кто-то запускает git-gc одновременно, я согласен, что это возможная проблема, но я подозреваю, что вы можете игнорировать это на практике.

Для загруженного многопользовательского сервера я рекомендую полностью отключить auto-gc и перепаковать вручную с помощью " -k ", чтобы быть в безопасности.

Вот почему страница man git gc теперь включает в себя:

С другой стороны, когда " git gc " запускается одновременно с другим процессом, существует риск того, что он удалит объект, который использует другой процесс, но не создал ссылку на него. Это может просто вызвать сбой другого процесса или может повредить хранилище, если другой процесс позже добавит ссылку на удаленный объект.

Git имеет две функции, которые значительно уменьшают эту проблему:

  • Любой объект с временем модификации, более --prune дата --prune сохраняется вместе со всем доступным из него.

  • Большинство операций, которые добавляют объект в базу данных, обновляют время модификации объекта, если оно уже присутствует, так что применяется # 1.

Однако этим функциям не хватает полного решения, поэтому пользователям, которые одновременно запускают команды, приходится сталкиваться с некоторым риском повреждения (который на практике кажется низким), если они не отключают автоматический сбор мусора с помощью git config gc.auto 0.,


Обратите внимание на последнее предложение, включающее "если они не отключают автоматический сбор мусора": Git 2.22 (Q2 2019) исправляет документацию gc.

См совершают 0044f77, совершает daecbf2, совершает 7384504, совершают 22d4e3b, совершает 080a448, совершает 54d56f5, совершают d257e0f, совершает b6a8d09 (07 Apr 2019), а также совершать fc559fb, совершает cf9cd77, совершает b11e856 (22 марта 2019) путем Эвар Arnfjord Bjarmason (avar)
(Объединено Junio C Hamano - gitster - в коммите ac70c53, 25 апреля 2019 г.)

gc docs: удалить неверную ссылку на gc.auto=0

Вероятность повреждения хранилища из-за " gc " не имеет ничего общего с тем, был ли этот gc вызван с помощью " gc --auto ", а с gc --auto других параллельных операций.

Это уже отмечено ранее в параграфе, поэтому нет никаких оснований предполагать это здесь. Из остальной части документации пользователь может сделать вывод, что " gc " будет запускаться автоматически, если не установлено gc.auto=0, и нам не следует путать проблему, подразумевая, что " gc --auto " каким-то образом более склонен вызывать повреждение чем обычный " gc ".

Что ж, это в том смысле, что блокирующий " gc " не позволит вам делать что-либо еще в этом конкретном окне терминала, но пользователи могут иметь другое окно или беспокоиться о том, как одновременный " gc " на сервере может вызвать коррупция.

Ответ 3

Если я запускаю git status на нескольких репозиториях одновременно на одном компьютере, у меня возникают серьезные проблемы. Я собираюсь подать отчет об этом. Я не вижу причин, почему это не должно быть возможно или почему это должно вызывать проблемы.