Сохранение прав доступа к файлам с помощью Git
Я хочу управлять версиями моего веб-сервера, как описано в разделе Управление версиями для моего веб-сервера, путем создания репозитория git из моего /var/www directory. Я надеялся, что тогда я смогу переместить веб-контент с нашего сервера разработки на github, вытащить его на наш производственный сервер и провести остаток дня в пуле.
по-видимому, излом в моем плане заключается в том, что Git не будет уважать права доступа к файлам (я не пробовал, только читал об этом сейчас.) Я думаю, это имеет смысл в том, что разные коробки могут иметь разные настройки пользователя/группы. Но если бы я хотел заставить разрешения распространяться, зная, что мои серверы настроены одинаково, есть ли у меня какие-либо варианты? Или есть более простой способ, что я пытаюсь сделать?
7 ответов:
The
git-cache-metaупоминается в так вопрос"git-как восстановить права доступа к файлам git считает, что файл должен быть?" (и git FAQ) является более staightforward подход.идея в том, чтобы хранить в
.git_cache_metaфайл разрешения файлов и каталогов.
Это отдельный файл, который не версируется непосредственно в репозитории 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Так ты:
- пакета РЕПО и сохраните соответствующие права доступа к файлам.
- скопируйте эти два файла на удаленный сервер
- восстановить РЕПО там, и применить разрешение
Git-это система управления версиями, созданная для разработки программного обеспечения, поэтому из всего набора режимов и разрешений она хранит только исполняемый бит (для обычных файлов) и бит символьной ссылки. Если вы хотите сохранить полные разрешения, вам нужен сторонний инструмент, например
git-cache-meta( упомянутый VonC), или Метахранилища (используется etckeeper). Или вы можете использовать IsiSetup, который IIRC использует git в качестве бэкэнда.посмотреть интерфейсы, интерфейсы и инструменты страница на Git Wiki.
Это довольно поздно, но может помочь некоторым другим. Я делаю то, что вы хотите сделать, добавив два крючка git в мой репозиторий.
.git / hooks / pre-commit:
#!/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-лучший способ. Добавьте сценарии предварительной фиксации и последующей проверки. Не забудьте назвать их точно так же, как это делает 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 hook здесь (разбор вывода из
git ls-files). Эти скрипты мне легче понять, код git-cache-meta довольно более сложный. Можно сохранить git-cache-meta в пути и написать сценарии pre-commit и post-checkout, которые будут его использовать.пробелы в именах файлов-это проблема с обоими Скрипты этого 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 jail делает операционную систему оптимальной. Текущая версия 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это также сохранит права доступа к каталогу.
Comments