не удалось заблокировать refs/heads/master удаленное голое репо

Мои проблемы относятся к ситуации, описанной в этом сообщении. В двух словах, есть удаленное голое и не голое репо. Согласно плану, немногие люди (включая меня) должны иметь возможность вносить свои изменения в голое репо. Файл hooks/post-receive позволяет автоматически вносить эти изменения в не голое репо на сервере. Это содержимое файла:

!/bin/sh
cd /data/11_prywatne/14_Pawel/repo_pawel_non_bare/deploy || exit
unset GIT_DIR
git pull origin master

`chmod g+rwx -R /data/11_prywatne/14_Pawel/repo_pawel_non_bare/deploy/ &> /dev/null`

Все шло хорошо, пока я был единственным человеком, который толкал и тянул к не голому репо. Однако однажды у другого человека git push origin master возникли некоторые проблемы. Например, при попытке git pull origin master в удаленном не голом репо (я знаю, что это не обязательно, так как есть hooks/post-receive) я получил эту ошибку:

fatal: Couldn't find remote ref master
fatal: The remote end hung up unexpectedly

Я попытался проверить с помощью git log (на удаленном не голом), что такое история коммитов, и получил эту ошибку:

error: Could not read <hash of the commit made by the other person>
fatal: Failed to traverse parents of commit 68e6227f4c4f84843ed7dd4fc03a159

git status (на удаленном не голом) возвращает следующий вывод:

# On branch master
error: Could not read <hash of the commit made by the other person>
error: Could not read <hash of the commit made by the other person>
fatal: Failed to traverse parents of commit 68e6227f4c4f84843ed7dd4fc03a15967051a97f

git push origin master (на удаленном не голом) возвращает:

error: Could not read <hash of the commit made by the other person>
fatal: Failed to traverse parents of commit 68e6227f4c4f84843ed7dd4fc03a15967051a97f
error: pack-objects died with strange error

(еще на пульте не голом) потом решил git reset --hard и вроде все нормально, но git push origin master меня достает:

error: unable to resolve reference refs/heads/master: Permission denied
remote: error: failed to lock refs/heads/master
To /data/11_prywatne/14_Pawel/gole.git/
 ! [remote rejected] master -> master (failed to lock)
error: failed to push some refs to '/data/11_prywatne/14_Pawel/gole.git/'
[user@server deploy]$ git pull origin master
fatal: git upload-pack: cannot find object <hash of the commit made by the other person>:
fatal: The remote end hung up unexpectedly

Я переключился на свое локальное репо и попытался нажать. Я получил те же ошибки, которые указывали на то, что проблема вызвана Permission denied. Я попросил другого человека установить групповые разрешения для файла, который находится в голом репо refs/heads/master. Проблема вроде бы решилась, но при попытке git push origin master возникла другая:

error: Ref refs/heads/master is at <hash of the commit made by the other person> but expected 0000000000000000000000000000000000000000
remote: error: failed to lock refs/heads/master
To server_ip:/data/11_prywatne/14_Pawel/gole.git/
 ! [remote rejected] master -> master (failed to lock)
error: failed to push some refs to 'user@server_ip:/data/11_prywatne/14_Pawel/gole.git/'

При попытке git pull origin master я получаю:

fatal: git upload-pack: cannot find object <hash of the commit made by the other person>:
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Просто для уточнения. Это содержимое .git/config на моей локальной машине:

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true
[remote "origin"]
        url = user@server_ip:/data/11_prywatne/14_Pawel/gole.git/
        fetch = +refs/heads/*:refs/remotes/origin/*

Файл .git/config на компьютере другого человека отличается только URL-адресом, на который он указывает (user2@server:/data/11_prywatne/14_Pawel/gole.git/).

Тот же файл, но в не голом репо на сервере:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = /data/11_prywatne/14_Pawel/gole.git/
[branch "master"]
        remote = origin
        merge = refs/heads/master

Возможно, я пропустил некоторые шаги при создании не голого репо. Должен ли я рассмотреть некоторые внутренние параметры git, которые позволяют создавать общие не голые репозитории? Указывает ли мое использование chmod на то, что я совершил ошибку? Как я могу решить проблему с ?


person balkon16    schedule 22.02.2019    source источник


Ответы (1)


Это проблема с правами доступа к файловой системе, вероятно, вызванная тем, что люди, отправляющие данные в пустой репозиторий, делают это, используя разные системные учетные записи. Вы должны помнить, что скрипты ловушек запускаются под одной и той же учетной записью. Если какое-либо из разрешений как в чистом, так и в обычном репозитории слишком ограничено, пользователь А не сможет пройти через это полностью после того, как пользователь Б также отправит — некоторые файлы и внутренний Git подкаталоги будут принадлежать A, а некоторые B.

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

Однако этого все же недостаточно, потому что --shared влияет только на собственные метаданные Git, а не на рабочее дерево. Ваша загрузка все еще может завершиться неудачей из-за невозможности фактического извлечения файлов. Каждый раз, когда операция извлечения создает новые каталоги, разрешения для них могут быть слишком строгими.

Исправление этого выходит за рамки Git - вы можете изучить:

  • Изменение всеми пользователями umask по умолчанию в своих учетных записях на этом компьютере;
  • Установка общей основной группы пользователей для всех этих пользователей (не всегда возможно) ИЛИ
  • Использование списков контроля доступа POSIX (которые, по общему признанию, могут сбивать с толку).

Если вы хотите обойти эти проблемы, другой вариант — обновить репозиторий в часто запускаемом cronjob, чтобы вы могли быть уверены, что он каждый раз запускается одним и тем же пользователем.

person Jan Krüger    schedule 22.02.2019
comment
Спасибо за ваш комментарий. Это разъясняет, какими должны быть мои следующие шаги. Можно ли реализовать одно из решений в файле post-receive? Я считаю, что все пользователи, которые выталкивают/извлекают из голого репо, находятся в одной группе. - person balkon16; 22.02.2019
comment
@ balkon16 balkon16, если все взаимодействие с не голым репо происходит через хук post-receive, тогда да, что-то вроде chmod -f -R g+w .; chgrp -f -R <common group> . (после извлечения) может работать. Вторая часть необязательна, если рассматриваемая группа является основной группой для всех пользователей. Также имейте в виду, что это работает только в том случае, если хук post-receive является единственным способом взаимодействия пользователей с не голым репо. - person Jan Krüger; 22.02.2019