Сохранение прав доступа к файлам с помощью Git
Я хочу контролировать версию моего веб-сервера, как описано в контроля версий для моего веб-сервера, создав git-РЕПО из моего /var/www directory
. Я надеялся, что тогда я смогу перенести веб-контент с нашего dev-сервера на github, вытащить его на наш производственный сервер и провести остаток дня в пуле.
по-видимому, излом в моем плане заключается в том, что Git не будет уважать права доступа к файлам (я не пробовал, только читал об этом сейчас.) Я думаю, это имеет смысл в что разные коробки могут иметь разные настройки пользователя/группы. Но если бы я хотел заставить разрешения распространяться, зная, что мои серверы настроены одинаково, есть ли у меня какие-либо варианты? Или есть более простой способ, что я пытаюсь сделать?
7 ответов
на git-cache-meta
упоминается в так вопрос"git-как восстановить права доступа к файлу git думает, что файл должен быть?" (и git FAQ) является более staightforward подход.
идея в том, чтобы хранить в .git_cache_meta
file разрешения файлов и каталогов.
Это отдельный файл, не версионный непосредственно в репозитории Git.
вот почему использование это:
$ git bundle create mybundle.bdl master; git-cache-meta --store
$ scp mybundle.bdl .git_cache_meta machine2:
#then on machine2:
$ git init; git pull mybundle.bdl master; git-cache-meta --apply
Так ты:
- bundle ваше РЕПО и сохраните соответствующие права доступа к файлам.
- скопируйте эти два файла на удаленный сервер
- восстановить РЕПО там, и применить разрешение
Git-это система управления версиями, созданная для разработки программного обеспечения, поэтому из всего набора режимов и разрешений она хранит только исполняемый бит (для обычных файлов) и бит символической ссылки. Если вы хотите сохранить полные разрешения, вам нужен сторонний инструмент, например git-cache-meta
(упоминается VonC), или Метахранилища (используется etckeeper). Или вы можете использовать IsiSetup, который IIRC использует git в качестве бэкэнда.
посмотреть интерфейсы, интерфейсы и инструменты страница на Git Wiki.
Это довольно поздно, но может помочь некоторым другим. Я делаю то, что вы хотите сделать, добавив два крючка git в мой репозиторий.
.git / hooks / предварительная фиксация:
#!/bin/bash
#
# A hook script called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if it wants
# to stop the commit.
SELF_DIR=`git rev-parse --show-toplevel`
DATABASE=$SELF_DIR/.permissions
# Clear the permissions database file
> $DATABASE
echo -n "Backing-up file permissions..."
IFS_OLD=$IFS; IFS=$'\n'
for FILE in `git ls-files`
do
# Save the permissions of all the files in the index
echo $FILE";"`stat -c "%a;%U;%G" $FILE` >> $DATABASE
done
IFS=$IFS_OLD
# Add the permissions database file to the index
git add $DATABASE
echo "OK"
.git / hooks / post-checkout:
#!/bin/bash
SELF_DIR=`git rev-parse --show-toplevel`
DATABASE=$SELF_DIR/.permissions
echo -n "Restoring file permissions..."
IFS_OLD=$IFS; IFS=$'\n'
while read -r LINE || [[ -n "$LINE" ]];
do
FILE=`echo $LINE | cut -d ";" -f 1`
PERMISSIONS=`echo $LINE | cut -d ";" -f 2`
USER=`echo $LINE | cut -d ";" -f 3`
GROUP=`echo $LINE | cut -d ";" -f 4`
# Set the file permissions
chmod $PERMISSIONS $FILE
# Set the file owner and groups
chown $USER:$GROUP $FILE
done < $DATABASE
IFS=$IFS_OLD
echo "OK"
exit 0
первый крючок вызывается, когда вы" фиксируете " и будете читать права собственности и разрешения для всех файлов в репозитории и хранить их в файле в корне вызываемого репозитория .разрешения, а затем добавить .файл разрешений для фиксации.
второй крюк вызывается, когда вы "checkout" и будет проходить через список файлов в .файл разрешений и восстановить права собственности и разрешения этих файлов.
- вам может потребоваться выполнить фиксацию и проверку с помощью sudo.
- убедитесь, что сценарии pre-commit и post-checkout имеют разрешение на выполнение.
в случае, если вы входите в это прямо сейчас, я только что прошел через это сегодня и могу подвести итог, где это стоит. Если вы еще не пробовали это, некоторые детали здесь могут помочь.
Я думаю, что подход @Omid Ariyan-лучший способ. Добавьте сценарии pre-commit и post-checkout. Не забудьте назвать их точно так же, как это делает Omid, и не забудьте сделать их исполняемыми. Если вы забудете любой из них, они не имеют никакого эффекта, и вы запускаете "git commit" снова и снова, задаваясь вопросом, почему ничего не происходит:) кроме того, если вы вырезаете и вставляете из веб-браузера, будьте осторожны, чтобы кавычки и галочки не были изменены.
если вы запустите сценарий предварительной фиксации один раз (запустив git commit), то файл .будут созданы разрешения. Вы можете добавить его в репозиторий, и я думаю, что нет необходимости добавлять его снова и снова в конце сценария предварительной фиксации. Но это не больно, я думаю (надеюсь).
есть несколько небольших проблем с именем каталога и наличие пробелов в именах файлов в сценариях Omid. Пробелы были проблемой здесь, и у меня были некоторые проблемы с исправлением IFS. Для записи этот сценарий предварительной фиксации работал правильно для меня:
#!/bin/bash
SELF_DIR=`git rev-parse --show-toplevel`
DATABASE=$SELF_DIR/.permissions
# Clear the permissions database file
> $DATABASE
echo -n "Backing-up file permissions..."
IFSold=$IFS
IFS=$'\n'
for FILE in `git ls-files`
do
# Save the permissions of all the files in the index
echo $FILE";"`stat -c "%a;%U;%G" $FILE` >> $DATABASE
done
IFS=${IFSold}
# Add the permissions database file to the index
git add $DATABASE
echo "OK"
теперь, что мы получим от этого?
The .файл разрешений находится на верхнем уровне репозитория git. Он имеет одну строку на файл, вот верхняя часть моего примера:
$ cat .permissions
.gitignore;660;pauljohn;pauljohn
05.WhatToReport/05.WhatToReport.doc;664;pauljohn;pauljohn
05.WhatToReport/05.WhatToReport.pdf;664;pauljohn;pauljohn
как вы можете видеть, у нас есть
filepath;perms;owner;group
в комментариях о этот подход, один из плакатов жалуется, что он работает только с тем же именем пользователя, и это технически верно, но это очень легко исправить. Обратите внимание, что скрипт post-checkout имеет 2 части действия,
# Set the file permissions
chmod $PERMISSIONS $FILE
# Set the file owner and groups
chown $USER:$GROUP $FILE
поэтому я оставляю только первый, это все, что мне нужно. Мое имя пользователя на веб-сервере действительно отличается, но что более важно, вы не можете запустить chown, если вы не корень. Может запустить "chgrp", однако. Достаточно ясно, как это использовать.
в первом ответ в этом посте, тот, который наиболее широко принят, предложение так использовать git-cache-meta, скрипт, который выполняет ту же работу, что и скрипты крючка pre / post здесь (разбор вывода из git ls-files
). Эти скрипты мне легче понять, код git-cache-meta более сложный. Можно сохранить git-cache-meta в пути и написать сценарии предварительной фиксации и после проверки, которые будут его использовать.
пробелы в именах файлов-это проблема с обоими Скрипты этого Omid. В сценарии post-checkout вы будете знать, что у вас есть пробелы в именах файлов, если вы видите такие ошибки
$ git checkout -- upload.sh
Restoring file permissions...chmod: cannot access '04.StartingValuesInLISREL/Open': No such file or directory
chmod: cannot access 'Notebook.onetoc2': No such file or directory
chown: cannot access '04.StartingValuesInLISREL/Open': No such file or directory
chown: cannot access 'Notebook.onetoc2': No such file or directory
Я проверяю решения для этого. Вот то, что, кажется, работает, но я тестировал только в одном случае
#!/bin/bash
SELF_DIR=`git rev-parse --show-toplevel`
DATABASE=$SELF_DIR/.permissions
echo -n "Restoring file permissions..."
IFSold=${IFS}
IFS=$
while read -r LINE || [[ -n "$LINE" ]];
do
FILE=`echo $LINE | cut -d ";" -f 1`
PERMISSIONS=`echo $LINE | cut -d ";" -f 2`
USER=`echo $LINE | cut -d ";" -f 3`
GROUP=`echo $LINE | cut -d ";" -f 4`
# Set the file permissions
chmod $PERMISSIONS $FILE
# Set the file owner and groups
chown $USER:$GROUP $FILE
done < $DATABASE
IFS=${IFSold}
echo "OK"
exit 0
поскольку информация о разрешениях является одной строкой за раз, я устанавливаю IFS в$, Поэтому только разрывы строк рассматриваются как новые вещи.
Я читал, что очень важно установить переменную среды IFS обратно так, как она был! Вы можете понять, почему сеанс оболочки может пойти плохо, если вы оставите $ единственным разделителем.
в pre-commit / post-checkout опция будет использовать утилиту" mtree "(FreeBSD) или" Fmtree "(Ubuntu), которая " сравнивает файловую иерархию со спецификацией, создает спецификацию для файловой иерархии или изменяет спецификацию."
по умолчанию установлены флаги, gid, link, mode, nlink, size, time, type и uid. Это можно приспосабливать к специфической цели с переключателем-k.
Я работаю на FreeBSD 11.1, концепция виртуализации тюрьмы freebsd делает операционную систему оптимальной. Текущая версия Git, которую я использую, - 2.15.1, я также предпочитаю запускать все на сценариях оболочки. Имея это в виду, я изменил приведенные выше предложения следующим образом:
git push: .git/hooks / pre-commit
#! /bin/sh -
#
# A hook script called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if it wants
# to stop the commit.
SELF_DIR=$(git rev-parse --show-toplevel);
DATABASE=$SELF_DIR/.permissions;
# Clear the permissions database file
> $DATABASE;
printf "Backing-up file permissions...\n";
OLDIFS=$IFS;
IFS=$'\n';
for FILE in $(git ls-files);
do
# Save the permissions of all the files in the index
printf "%s;%s\n" $FILE $(stat -f "%Lp;%u;%g" $FILE) >> $DATABASE;
done
IFS=$OLDIFS;
# Add the permissions database file to the index
git add $DATABASE;
printf "OK\n";
git pull: .git/hooks / post-merge
#! /bin/sh -
SELF_DIR=$(git rev-parse --show-toplevel);
DATABASE=$SELF_DIR/.permissions;
printf "Restoring file permissions...\n";
OLDIFS=$IFS;
IFS=$'\n';
while read -r LINE || [ -n "$LINE" ];
do
FILE=$(printf "%s" $LINE | cut -d ";" -f 1);
PERMISSIONS=$(printf "%s" $LINE | cut -d ";" -f 2);
USER=$(printf "%s" $LINE | cut -d ";" -f 3);
GROUP=$(printf "%s" $LINE | cut -d ";" -f 4);
# Set the file permissions
chmod $PERMISSIONS $FILE;
# Set the file owner and groups
chown $USER:$GROUP $FILE;
done < $DATABASE
IFS=$OLDIFS
pritnf "OK\n";
exit 0;
Если по какой-то причине вам нужно, чтобы воссоздать сценарий .разрешения вывод файла должен иметь следующий формат:
.gitignore;644;0;0
для a .файл gitignore с 644 разрешениями, предоставленными root: wheel
обратите внимание, что мне пришлось внести несколько изменений в параметры stat.
наслаждайтесь,
одно дополнение к ответу @Omid Ariyan-это разрешения на каталоги. Добавьте это после for
петли done
в своем pre-commit
сценарий.
for DIR in $(find ./ -mindepth 1 -type d -not -path "./.git" -not -path "./.git/*" | sed 's@^\./@@')
do
# Save the permissions of all the files in the index
echo $DIR";"`stat -c "%a;%U;%G" $DIR` >> $DATABASE
done
Это также сохранит разрешения каталога.