Git меняет umask по умолчанию при обновлении файла

У меня проблема с Git'ом. Я искал решение в Google и в StackOverflow, но ничего не помогает.

Проблема в том, что каждый раз, когда git обновляет какой-либо файл в рабочем каталоге (когда я извлекаю ветки или объединяю ветку и т. д.), права доступа к файлу изменяются таким образом, что добавляется флаг «доступен для записи в группу». И мой apache показывает «Ошибка 500» для файла, если он доступен для записи в группу.

Пример: у меня есть файл index.php. Разрешения "-rwxr-xr-x". Текущая (активная) ветвь является master. Этот файл был изменен в ветке "develop". Я выполняю "git checkout develop" и файл index.php получает права "-rwxrwxr-x" (добавляется запись в группу). И мой сайт перестает работать. Поскольку apache не разрешает этот флаг в файлах php (я не знаю, почему, но я не могу это изменить).

Каждый раз, когда я запускаю «git checkout development», мне нужно также выполнить «chmod g-w index.php». Я не люблю выполнять две команды (а иногда я забываю выполнить это, и мой сайт не работает).

Что я могу сделать, чтобы решить эту проблему? Я думаю, что это что-то связанное с umask. Я сделал несколько трюков, которые нашел в Интернете, но ничего не работает.

Спасибо.


person Roman Gelembjuk    schedule 20.07.2012    source источник
comment
Есть ли какая-то причина, по которой вы не можете просто установить свой umask соответствующим образом (например, на 0022 или аналогичный)?   -  person CB Bailey    schedule 20.07.2012
comment
Как это сделать? Чтобы установить umask? Это изменение системы или только изменение git? Если система, то я не могу изменить это   -  person Roman Gelembjuk    schedule 20.07.2012
comment
Просто запустите umask 0022. Чтобы установить его для интерактивных сеансов, поместите эту команду в свою .bashrc или эквивалентную оболочку. Устанавливать всегда, но это в вашем .profile.   -  person CB Bailey    schedule 20.07.2012
comment
Я не хочу менять какие-либо системные настройки. Сайт работает с этим пользователем. Я боюсь, что это может повлиять на что-то еще. Есть ли способ решить проблему только с изменением настроек git? Я знаю, что в git есть перехватчики обновлений. Но я не могу найти, как это решить с помощью хуков.   -  person Roman Gelembjuk    schedule 20.07.2012
comment
Это не проблема git, это проблема umask; если сайт работает от имени этого пользователя и работает только в том случае, если этот пользователь создает файл, который не доступен для групповой записи, то, несомненно, вы хотите изменить umask этого пользователя на 0022. (.profile являются пользователем настройки, а не системные настройки)   -  person CB Bailey    schedule 20.07.2012


Ответы (4)


Быстрый ответ: эта функция оболочки должна быть помещена в ваш файл ~/.profile. Далее следует объяснение.

git(){(umask 0022; command git "$@")}

umask является свойством процесса. Он наследуется от родительского процесса и впоследствии может быть изменен изнутри. Команда для изменения umask также обычно называется umask.

Git не имеет опции конфигурации для установки umask, он не меняет свою umask после выполнения. Вы должны установить umask Git извне, пусть он будет унаследован от родительского процесса (обычно оболочки).

Ммм, похоже, тебе не нравится идея, что что-то кроме git изменило umask. Итак, давайте изменим его только при выполнении git.

Когда оболочка выполняет строку, она берет первое слово в строке и пытается найти функцию с таким именем. Только если его нет, он пытается найти команду с таким именем в PATH. Функция, которую я написал выше, называется git, поэтому любой прямой вызов git теперь выполняет ее вместо команды git.

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

Однако функция также показывает, как обойти себя. Если вы вызываете git через command git или даже /usr/bin/git, функция вызываться не будет. Однако для любого приличного использования этого вполне достаточно.

person Palec    schedule 04.11.2013

Разрешать выполнение файла в виде двоичного файла довольно опасно. Во всяком случае, я решил проблему с umask. Мой post-receive скрипт выглядит так:

!/bin/sh
umask 002
GIT_WORK_TREE=/var/www/site git checkout -f

Итак, file permissions установлено в 664, а directory permissions установлено в 775, что меня вполне устраивает.

P.S. Установка umask в файле .profile пользователя git не имеет никакого эффекта, и я не понимаю, почему, пожалуйста, прокомментируйте, если вы знаете, почему это происходит.

person zogby    schedule 22.08.2014
comment
umask 0022 будет иметь больше смысла для обычного веб-сервера, поскольку только владелец будет иметь право на запись: в результате file permission 644 и directory permissions 755 - person Laszlo Schürg; 16.03.2018

Я только что столкнулся с этой проблемой при проверке репозитория в домашнем каталоге, смонтированном через NFS на Ubuntu 14.04 (Trusty) с использованием ядра Linux Xenial версии 4.x с бэкпортом. Git clone в локальный каталог был в порядке. Еще более странно: второй сервер Ubuntu 14.04 не обнаружил такой же проблемы в том же смонтированном каталоге.

После долгих поисков я смог увидеть, используя strace, что git вызывает системный вызов open() для создания каждого файла с параметрами O_CREAT, O_WRONLY и O_EXCL и режимом 0666, но затем следующий системный вызов был fstat() против файл и сказал мне, что это режим 0700. В моем случае проблема затронула только определенные файлы в репозитории. Несмотря на то, что git ls-index показывает режим 0644 для большинства файлов, некоторые из них создавались правильно, а другие нет; хотя это всегда были одни и те же файлы с неправильными разрешениями на клон.

Я заметил разницу в версии ядра между двумя системами, а затем обнаружил следующую ошибку: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1654288

Обновление ядра до 4.4.0-98 (с 4.4.0-59) исправило это для меня. Я проверил некоторые хосты, все еще использующие ядро ​​​​Linux версии 3.x, и у них не было проблем.

person JonathanDIT    schedule 09.02.2018

Использование хуков для изменения режима файла после проверки устраняет проблему после того, как она уже возникла. У вас уже есть плохой файловый режим в файловой системе при выполнении хука. Если запрос поступает как раз между проверкой и выполнением хука, сервер ответит ошибкой 500. Но вас все равно может заинтересовать это решение.

Вам нужен post-checkout хук, запускающий chmod g-w все необходимые файлы. Хук .git/hooks/post-checkout должен быть исполняемым и получает текущий HEAD в качестве второго параметра ($2 в оболочке). Крючок может выглядеть так:

#!/bin/bash
git ls-files -z --with-tree="$2" | xargs -0 chmod g-w --

Поскольку хук не получает список проверенных файлов, это может быть наилучшей возможной реализацией. Он изменяет режим всех файлов в текущем HEAD.

person Palec    schedule 04.11.2013