Git использует несколько подходов для обработки этого случая, а libgit2 использует те же подходы для совместимости.
Когда Git необходимо обновить файл с фиксированным именем, таким как индекс или ссылка, он создает файл с тем же именем, но оканчивается на .lock
, O_CREAT
и O_EXCL
, а затем записывает новое содержимое в этот файл. Затем он использует переименование atomi c поверх существующего файла. В системах Unix это означает, что процессы со старым открытым файлом не увидят изменений, а новые процессы откроют новый файл.
Если вы записываете объект в хранилище объектов, например, дерево или фиксацию, это не связано с гонками, потому что у него однозначное название. Файл либо существует, либо нет, а если нет, он создается как временный файл и переименовывается на место. Переименование означает, что если идентичный объект уже существует, он будет заменен идентичной копией.
Теперь возможно, что вы хотите записать файл, например индекс, и кто-то другой уже делает это , и в этом случае вам придется подождать, пока файл блокировки не исчезнет. Обычно время ожидания довольно короткое, поэтому ожидание не проблема. Для таких вещей, как индекс, libgit2 предлагает индексы в памяти, которые не требуют блокировки и от которых легче отказаться, если вы решите, что они вам не нужны.
Обратите внимание, что Git не гарантирует atomi c операций в рабочем дереве, потому что действительно невозможно полностью откатиться, если что-то go не так. Если вы просто имеете дело с содержимым репозитория и не обновляете рабочее дерево, тогда Git должен быть свободен от состояний гонки и достаточно производительным для нескольких пользователей.