Есть несколько возможных причин такого рода неудач. Согласно comment это оказалось быть устаревшим master.lock
файлом на сервере. Достаточно удалить вручную.
Поскольку может быть более одной причины сбоя, не так уж полезно давать только один конкретный ответ. Однако мы можем обрисовать здесь общий процесс и то, что может пойти не так.
Помните, что имена ветвей и тегов — это особые формы refs или references. Каждый из них просто содержит один хэш-идентификатор. Имена тегов обычно содержат хэш-идентификатор либо объекта тега, который образует аннотированный тег, либо объекта фиксации, и после создания никогда не меняются. Однако имена веток идентифицируют одну фиксацию в цепочке коммитов, и эта фиксация считается последней фиксацией, являющейся частью этой ветки. (Могут быть последующие фиксации, но они не содержатся в этой ветке. Обратите внимание, что фиксация, идентифицированная именем ветки, может содержаться в других ветвях.) результатом этого является то, что эти значения регулярно меняются по мере роста ветвей. Таким образом, необходимо обновить пару ‹имя, значение›.
Эти пары имя-значение, вероятно, должны храниться в какой-то транзакционной базе данных, но это не так. В настоящее время Git (начиная со всех выпусков вплоть до сегодняшней версии 2.26.2 и, возможно, еще долго) хранит все эти ссылки в одном или обоих из двух мест: либо в одном плоском файле с именем packed-refs
, либо в отдельных файлах, хранящихся в файловая система, например, refs/heads/master
. Чтобы найти имя, Git сначала проверяет, существует ли отдельный файл. Если это так, файл будет иметь правильное значение. Если нет, Git проверяет, существует ли это имя в файле packed-refs
, и если да, использует это значение. Если оба поиска не увенчались успехом, имя не существует.
Чтобы гарантировать, что любое обновление является атомарным — что никакая другая команда Git не может обновить имя, пока его обновляет одна команда Git, — Git использует тщательную последовательность создания .lock
файлов. Например, чтобы обновить refs/heads/master
, Git сначала создает refs/heads/master.lock
.1 ОС хоста должна (и делает) предоставить для этого операцию «создать файл, но завершиться ошибкой, если он уже существует».
Здесь все может пойти не так. Предположим, например, что каталог (или папка, если вы предпочитаете этот термин) refs/heads/
отказывает в разрешении на создание нового файла идентификатору пользователя, который обрабатывает процесс git push
. В этом случае создание master.lock
завершится ошибкой типа "отказано в доступе".
В вашем конкретном случае файл master.lock
уже существовал. Обычно такие файлы создаются, записываются, а затем удаляются или переименовываются. Однако в случае сбоя питания, сбоя системы или другого внезапного завершения программы Git система не остается в хорошем состоянии. В частности, файл .lock
продолжает существовать.
В случае сбоев питания или сбоев системы можно войти и удалить устаревшие файлы .lock
во время запуска системы. На практике это недостаточно распространено на большинстве серверов, чтобы с этим возиться — люди могут просто исправить свой Git-сервер вручную, как это сделали вы. Git-программы, как правило, не должны внезапно завершаться операционной системой, но некоторые системы используют «убийцы нехватки памяти» (OOM-killers), которые иногда могут вызывать такого рода проблемы.
1Создав соответствующий файл .lock
, Git запишет новое значение в файл блокировки, а затем с помощью операции атомарного переименования превратит файл master.lock
в файл с именем master
, удалив все предыдущие файлы. . Это снимает блокировку и сохраняет новое значение таким образом, что любая другая команда Git, которой требуется это значение, увидит новое.
Git использует ту же технику для создания index.lock
при обновлении своего индексного файла, но, поскольку записи индекса никогда не переносятся из одного Git в другой, любые сбои здесь всегда чисто локальны, а не во время git push
. У этого метода есть еще одна особенность, заключающаяся в том, что «транзакцию» можно «откатить», просто удалив файл блокировки, а не переименовав файл блокировки в основное имя.
Помните термин ACID при работе с базами данных: атомарность, согласованность, изоляция, долговечность. Метод файла .lock
обеспечивает атомарность и, если ОС делает правильные гарантии, согласованность и долговечность. Однако свойство изоляции полностью отсутствует: мы не можем обновлять одно поле базы данных отдельно. Вот почему Git использует отдельные файлы для каждой ссылки (за исключением случаев, когда это не так, через файл packed-refs
, который поэтому фактически доступен только для чтения: только одна программа Git, git pack-refs
, когда-либо обновляет его, используя собственную более сложную блокировку).
Отсутствие изоляции также может быть болезненным при работе с очень большим индексом. По этой причине Git может использовать режим «разделенного индекса», в котором некоторые записи (те, которые не менялись в последнее время) находятся во втором файле, а в основном .git/index
файле находятся только «активно изменяющиеся» записи.
(Использование реальной базы данных решило бы все эти проблемы, а также множество других, но настоящие базы данных сложны.)
person
torek
schedule
09.05.2020
git push origin master:master
? Честно говоря, я не могу объяснить, почему — я искал вашу ошибку, и это одно из наиболее распространенных предположений, но причины совершенно разные, и, насколько я могу судить, вы не попадаете ни в одну из них. Единственная общая черта заключается в том, что что-то не так с тем, что Git знает о ветках и реальных ветках. В одном случае он пытается нажать на имя ветки с неправильной заглавной буквой, в другой раз он должен был нажать на имя веткиa/b
, хотя веткаa
уже была. Или в локальном индексе git может быть просто мусор. - person VLAZ   schedule 08.05.2020git push origin master:master
выводит так же, какgit push origin master
. - person Miron   schedule 08.05.2020failed to lock
ваш Git сообщает об ошибке, переданной от другого Git, и сбой блокировки там, по крайней мере в этом случае, не связан с тем, что вы можете исправить со своей стороны. Вам нужно будет попросить кого-нибудь, у кого есть доступ к серверу, зайти, посмотреть, что не так, и исправить это там. - person torek   schedule 08.05.2020ref/heads
с сервера, на котором существовалmaster.lock
файл. После того, как я удалил файл,git push
удалось. Не могли бы вы опубликовать свою оценку в качестве ответа и объяснить возможные случаи, когда файл блокировки создается, пожалуйста? - person Miron   schedule 09.05.2020