Сохранение прав доступа к файлам с помощью Git



Я хочу управлять версиями моего веб-сервера, как описано в разделе Управление версиями для моего веб-сервера, путем создания репозитория git из моего /var/www directory. Я надеялся, что тогда я смогу переместить веб-контент с нашего сервера разработки на github, вытащить его на наш производственный сервер и провести остаток дня в пуле.



по-видимому, излом в моем плане заключается в том, что Git не будет уважать права доступа к файлам (я не пробовал, только читал об этом сейчас.) Я думаю, это имеет смысл в том, что разные коробки могут иметь разные настройки пользователя/группы. Но если бы я хотел заставить разрешения распространяться, зная, что мои серверы настроены одинаково, есть ли у меня какие-либо варианты? Или есть более простой способ, что я пытаюсь сделать?

849   7  

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

    Ничего не найдено.