невозможно перенести объекты в постоянное хранилище

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

По какой-то причине git нужна папка objects в репозитории на его ssh-сервере, куда пользователи push или pull. По какой-то причине (?) Git создает папки под объектами со случайными именами в диапазоне от 01 до ff.

Проблема в том, что папки под объектами принадлежат фактическому пользователю, который отправляет новую ревизию в этот репозиторий с разрешением доступа 775 — то есть только этот пользователь и пользователи в его группе могут писать в эту папку.

Поскольку репозиторий используется какое-то время, 255 возможных имен совпадают. Имя папки под объектами необходимо будет повторно использовать в ходе push. Если отправляющий пользователь не совпадает с тем, кто создал папку (например, несколько недель назад), он увидит сообщение об ошибке невозможно перенести объекты в постоянное хранилище из-за упомянутого нарушения прав.

Решение состоит в том, что отправляющий пользователь становится членом группы пользователя, который отправляет последний раз, используя то же имя папки objects.

Есть ли какой-либо механизм для git ssh-сервера, чтобы избежать такого конфликта более удобным способом? Как мне избежать добавления нового пользователя во все группы всех существующих пользователей, чтобы избежать конфликтов разрешений для папок objects?

git config core.sharedRepository=0660; stackoverflow.com/search?q=%5Bgit%5D+sharedrepository   —  person ngong    schedule 27.11.2020

@phd отличный совет!   —  person ngong    schedule 27.11.2020

@phd отлично! Сочувствие! Если по умолчанию не используется общий доступ, почему многие пользователи могут нажимать на репо, пока не появится это сбивающее с толку сообщение об ошибке? Я что-то сделал не так изначально? Мне нравится просто вводить pub-ключ нового пользователя в authorized_keys пользователя git.   —  person ngong    schedule 27.11.2020

См. также:  Git с Bitbucket

Я подозреваю, что вы сделали chmod -R g+w. На самом деле вам это нужно еще раз. После установки sharedRespoitory Git сам будет поддерживать групповую запись.   —  person ngong    schedule 27.11.2020

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. ngong

    Между комментариями phd о настройки режимов и eftshift0’s answer, у вас уже есть несколько практических подходов для решения этой проблемы. Вот теория, подтверждающая эти практические ответы.

    По какой-то причине git нужна папка objects в репозитории на своем ssh-сервере, куда пользователи нажимают или извлекают. По какой-то причине (?) Git создает папки под объектами со случайными именами в диапазоне от 01 до ff.

    На самом деле это с 00 по ff. В вашем случае происходит что-то немного странное; мы рассмотрим это немного позже.

    Прежде всего необходимо понять, что Git не хранит файлы. Git хранит в своей основной базе данных — мы вернемся к этому главному слову позже — это объекты. У этих объектов есть хеш-идентификаторы: например, имена в форме faefdd61ec7c7f6f3c8c9907891465ac9a2a1475. Хеш-идентификаторы, которые вы обычно видите — хотя часто сокращенно, например, faefdd61e — относятся к объектам фиксации, но на самом деле существует четыре типа объектов. Первым, конечно же, является фиксация; остальные три — это tree, blob и аннотированный тег.

    Содержимое файла попадает в объекты blob. Имена файлов разделяются на компоненты имени в знакомом для систем Unix / Linux стиле «каталог и имя файла» с помощью косой черты; эти компоненты имени, а также дополнительная информация по мере необходимости, входят в объекты дерева; а затем объект фиксации ссылается на объект дерева для хранения данных — файлов — для фиксации в сжатой и дедуплицированной форме хранилища объектов Git. Объекты аннотированных тегов существуют, так что аннотированные теги могут хранить данные, а также хэш-идентификатор фиксации (или любой другой хеш-идентификатор объекта, хотя необычно иметь объект аннотированного тега, который указывает на что-либо, кроме объекта фиксации).

    Следовательно, основная база данных любого репозитория Git — это база данных объектов. Сами объекты могут храниться как свободные объекты или как их противоположность: упакованные объекты (не плотные объекты, хотя упаковка действительно упаковывает их довольно плотно ????). Упакованные объекты хранятся в файле пакета, а файлы пакета находятся в каталоге objects в подкаталоге с именем pack. Ваш .git/objects/pack должен содержать один или несколько *.pack файлов, каждый из которых также имеет соответствующий файл *.idx. Мы вернемся немного позже, чтобы упаковать файлы.

    Свободные объекты хранятся вместе с каждым объектом в отдельном файле на уровне файловой системы. Имя объекта может быть dd1cf41e007a0036e18eef4b0acae505ec52f168. Если он должен быть сохранен как свободный объект, а не как упакованный, его имя уровня файловой системы будет dd/1cf41e007a0036e18eef4b0acae505ec52f168. Мы просто берем первые два символа шестнадцатеричного расширения идентификатора хэша с лицевой стороны и используем их как имя каталога, а оставшиеся символы используем как имя файла.

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

    Когда пользователи запускают git push (но не git pull), их Git вызывает другой Git. Их Git читает их репозиторий Git. Сервер Git читает и записывает репозиторий сервера. Их Git определяет, какие объекты фиксации у них есть, а сервер не хватает, и отправляет эти объекты фиксации. Две координаты Git и отправляющий Git также могут определить, какие еще объекты требуются.

    Когда у отправителя есть список всех необходимых объектов, он обычно собирает все эти объекты и записывает то, что Git называет тонким пакетом. Тонкий пакет — это пакет, который нарушает одно из обычных ограничений файла пакета, поэтому теперь пора описать, для чего предназначен файл пакета.

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

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

    Однако, как только мы сможем упаковать объекты, мы сможем выбрать один из этих объектов — вероятно, самую последнюю копию файла, так как это та, которую мы, скорее всего, извлечем, — и сохранить тот полностью, а затем сохраните другие версии файла в виде последовательностей инструкций: начните с большого файла, затем удалите 140 байтов в конце, например. 2 </ sup> Дельта-выражения могут использовать несколько объектов с помощью нескольких последовательностей инструкций и могут относиться к объектам, которые сами хранятся с использованием дельта-инструкций, если график объектов, используемых в этих конструкциях, не является круговым. Конечный результат, конечно, таков: если у нас есть 50 копий файла размером 10 МБ, каждая из которых немного отличается, файл pack содержит только файл размером 10 МБ плюс около 49 коротких модификаторов.

    Объекты, используемые для создания конечных объектов, называются дельта-базами. Как мы только что отметили, объект с дельта-сжатием может сам быть дельта-базой. Цепочка дельт называется цепочкой дельт, и распаковка такого объекта требует небольшой рекурсии. Пока файл пакета правильно сформирован, рекурсия никогда не будет бесконечной, так что это нормально; и мы можем использовать такие методы, как мемоизация, чтобы сделать это достаточно быстро, если это необходимо.

    В любом случае обычным ограничением для файла пакета является то, что он должен содержать каждый объект, который необходим для восстановления окончательного объекта. Тонкий пакет — это пакет, в котором мы позволяем отправляющему Git предполагать, что принимающий Git уже имеет некоторые объекты, и использовать эти объекты в качестве дельта-баз, не включая их в пакет. Таким образом, тонкий пакет действительно может быть очень маленьким: он идеально подходит для передачи по сети. 3

    В результате git push обычно отправляет тонкий пакет. Принимающий Git должен взять этот тонкий пакет и исправить его, чтобы сделать обычный пакет. Во время этого процесса не создаются незакрепленные предметы. Тот факт, что вы получаете незакрепленные предметы, указывает на то, что в ваших толчках не используются тонкие пакеты. Это не неправильно, но вы можете выяснить, почему это так.


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

    Обратите внимание, что все объекты Git полностью доступны только для чтения, потому что их имена хеш-идентификаторов создаются путем хеширования содержимого объектного файла. Каждый файл начинается с заголовка, указывающего тип объекта — один из четырех типов объекта — и размер, а байты типа и размера включаются в хэш-идентификатор, который случайно защитил Git от исходной атаки SHAttered (см. Как недавно обнаруженная коллизия SHA-1 влияет на Git?). Тем не менее, алгоритм хеширования в конечном итоге будет модернизирован до более стойкого. Этот переход будет интересным временем в том же смысле, что и 2020 год был интересным годом.

    2 Фактическая кодировка, я думаю, состоит всего из двух инструкций: взять n байтов из смещения o объекта obj </ em> и вставьте буквальную последовательность байтов S, но здесь можно представить любые инструкции. Все они более или менее эквивалентны. Можно добавить дополнительные инструкции, например, скопировать n байтов со смещения один раз или скопировать n байтов со смещения, повторить r раз или потребовать копию операция, чтобы указать количество копий, которые нужно сделать, или что-то еще, но это всего лишь небольшие изменения. Более богатый набор инструкций обычно предлагает больше возможностей сжатия за счет более сложного кода для поиска минимального сжатия и большего формата кодированных инструкций.

    3 Предполагается, что дешевый процессор, высокая пропускная способность сети.


    Заканчивать

    Начнем с git push. При этом отправляются объекты, обычно тонкими пакетами. Принимающий Git должен где-то хранить эти объекты или этот тонкий пакет: современные Git используют карантинную область, а старые Git просто выгружают их прямо в базу данных объектов.

    Отправив объекты, отправляющий Git теперь отправляет последовательность обновлений имени. Они влияют на базу данных name, которая является другой первичной базой данных в репозитории Git. Имена, хранящиеся в этой базе данных, — это имена веток, имена тегов, имена удаленного отслеживания и любые другие имена, которые Git сочтет полезными. Push обычно отправляет один или несколько запросов на обновление имени ветки и / или тега.

    Принимающему Git разрешено проверять и проверять эти запросы, используя полученные объекты (и, возможно, помещенные в карантин) для проверки всего. Если проверка проходит — если проверка не проводится, она просто проходит автоматически — получающий Git проверяет обновления имени. Обновления имени ветки должны быть либо принудительными, с флагом --force или + в команде git push, либо должны быть операциями быстрой перемотки вперед или новыми именами .

    Операция быстрой перемотки вперед оставляет имя в такой позиции, что, следуя графику фиксации назад, фиксация, идентифицированная предыдущей позицией, достижима из новой позиции. Другими словами, получающий Git может получить запрос на обновление имени ветки br1. Новая фиксация, идентифицированная обновленным именем, должна быть потомком фиксации, найденной в настоящее время по имени br1.

    Если с обновлением имени все в порядке, и все разрешено через хуки предварительного приема и обновления (если есть), которые выполнили проверку (если есть), принимающий Git принимает обновление и исправляет тонкий пакет или иным образом перемещает объекты вне карантина. В этом случае при необходимости вы будете создавать новые .git/objects/ каталоги.

    Git, выполняющий прием, создает эти каталоги с mkdir системными вызовами. Они используют как umask процесса Git, выполняющего mkdir, так и разрешения, предоставленные вызову mkdir. Право собственности на новые каталоги устанавливается правилами ОС: владельцем группы может быть идентификатор группы процесса или идентификатор группы родительского каталога. Использование трюка set-group-ID является довольно стандартным способом в системах Unix и Linux, чтобы сообщить ОС, чтобы она установила идентификатор группы для нового каталога на основе идентификатора группы содержащего каталог.

    Если ваш Git использует файлы пакетов — как обычно и должно быть — основная проблема будет заключаться в том, чтобы каталог .git/objects/pack и его содержимое имели права собственности и разрешения. Если ваш Git использует незакрепленные объекты, выясните почему, а также убедитесь, что новые каталоги здесь имеют права собственности и разрешения. Все они контролируются вашей ОС; Роль Git здесь — просто установить umask и передать правильные аргументы системным вызовам open и mkdir.

    Несмотря на то, что он был длинным, мне стоило прочитать каждое слово. Теперь я знаю, что делаю, когда играю с правами доступа в удаленных репозиториях. Супер! Однако остается последний вопрос: почему в моем случае не работает автоматический git gc по умолчанию. Выполнение этого вручную сработало. person ngong; 28.11.2020

    Хм. Учитывая ваше сообщение об ошибке, я думаю, что у вас есть Git, достаточно новый, чтобы иметь зону карантина; учитывая, что git gc --auto что-либо не делает, мне интересно, есть ли у вас Git из эпохи ошибок, когда git gc --auto дает сбой (по любой причине, которая может включать проблемы с разрешениями) и оставляет после себя файл трассировки, который приводит к сбою будущих git gc --auto операций . Я думаю, что в этом случае ручной gc выводит сообщение об ошибке. Я не уверен, почему вы заметили такое поведение. person ngong; 28.11.2020

    Думаю, я ошибался: git gc не запускается автоматически по умолчанию на удаленном ssh-сервере, где размещены только репозитории —bare. И, насколько я понял, git gc не так важен для репозиториев —bare, как для клиента. Надеюсь, теперь я понял. person ngong; 28.11.2020

    Что ж, git gc должен запускаться автоматически, но да, пока вы получаете файлы пакетов, а не отдельные объекты, это не так, как нужно. Хотя в какой-то момент вы создаете много файлов пакетов, и переупаковка, которая сжимает их до одного файла пакета, является хорошей идеей. (Git расширяет новый набор средств, чтобы все это работало лучше прямо сейчас, но, насколько мне известно, ни один из них не используется повсеместно.) person ngong; 28.11.2020

    хм — я запускаю git 2.17.1 на Ubuntu. Мои самые старые репозитории датируются апрелем 19-го на этом удаленном сервере. Все они — голые. Только действие — это толкать и тянуть от клиентов. Папки под объектами никогда не удаляются, за исключением того, что я делаю git gc manuall (на сервере). Следовательно, я прихожу к выводу, что git gc не работает по умолчанию. Как указать .gitconfig запускать git gc —auto при любом нажатии? person ngong; 29.11.2020

    Вы упомянули, что папки ниже objects никогда не удаляются (подразумеваемым автоматическим gc): есть ли у пользователя, запускающего ssh, разрешение на удаление из каталога .git? В противном случае тот, кто запускает push, также запускает auto-gc, и у него не будет разрешения на удаление пустого подкаталога в каталоге .git/objects. На самом деле это не вредно, это просто означает, что подкаталоги верхнего уровня накапливаются, даже когда они пусты. person ngong; 29.11.2020

  2. ngong

    Я легко могу придумать два способа:

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

    Другой подход заключается в использовании setgid в репо, чтобы группа любого файла, созданного внутри репо, оставалась согласованной. Затем возникает вопрос о том, чтобы сохранить разработчиков в правильной группе и убедиться, что их настройка umask разрешает rw на уровне группы, когда пользователь создает новый файл / объект в репо. https://en.m.wikipedia.org/wiki/Setuid

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: