Webサーバーのバージョン管理 で説明されているように、/var/www directory
からgitリポジトリを作成して、Webサーバーをバージョン管理します。私の希望は、その後、開発サーバーからgithubにWebコンテンツをプッシュし、それを運用サーバーにプルし、残りの時間をプールで過ごすことができるようになることでした。
どうやら私の計画の欠点は、Gitがファイルのアクセス許可を尊重しないことです(私はそれを試したことはありませんが、今それについて読んでいます)。しかし、サーバーが同じように構成されていることを知って、許可を強制的に伝達したい場合、オプションはありますか?または、私がやろうとしていることに近づく簡単な方法はありますか?
git-cache-meta
SO question " git-gitが考えるファイル許可を回復する方法ファイルはどうですか? "(および git FAQ )はより明確なアプローチです。
アイデアは、.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による言及 )、または Metastore (- etckeeper )。または、 IsiSetup を使用できます。IIRCはgitをバックエンドとして使用します。
インターフェース、フロントエンド、およびツール Git Wikiのページを参照してください。
これはかなり遅いですが、他の人を助けるかもしれません。リポジトリに2つの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 permissions..."
IFS_OLD=$IFS; IFS=$'\n'
for FILE in `git ls-files --full-name`
do
# Save the permissions of all the files in the index
echo $FILE";"`stat -c "%a;%U;%G" $FILE` >> $DATABASE
done
for DIRECTORY in `git ls-files --full-name | xargs -n 1 dirname | uniq`
do
# Save the permissions of all the directories in the index
echo $DIRECTORY";"`stat -c "%a;%U;%G" $DIRECTORY` >> $DATABASE
done
IFS=$IFS_OLD
# Add the permissions database file to the index
git add $DATABASE -f
echo "OK"
。git/hooks/post-checkout:
#!/bin/bash
SELF_DIR=`git rev-parse --show-toplevel`
DATABASE=$SELF_DIR/.permissions
echo -n "Restoring permissions..."
IFS_OLD=$IFS; IFS=$'\n'
while read -r LINE || [[ -n "$LINE" ]];
do
ITEM=`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/directory permissions
chmod $PERMISSIONS $ITEM
# Set the file/directory owner and groups
chown $USER:$GROUP $ITEM
done < $DATABASE
IFS=$IFS_OLD
echo "OK"
exit 0
最初のフックは、「コミット」するときに呼び出され、リポジトリ内のすべてのファイルの所有権と権限を読み取り、リポジトリのルートにある.permissionsというファイルに保存してから、.permissionsファイルをコミットに追加します。
2番目のフックは、「チェックアウト」するときに呼び出され、.permissionsファイル内のファイルのリストを調べて、それらのファイルの所有権と許可を復元します。
あなたが今ここに来ている場合のために、私は今日それをちょうど通り過ぎて、これが立っている場所を要約することができます。これをまだ試していない場合は、ここで詳細を確認してください。
@Omid Ariyanのアプローチが最良の方法だと思います。コミット前およびチェックアウト後のスクリプトを追加します。 Omidと同じ名前を付けることを忘れないでください。また、実行可能にすることを忘れないでください。これらのいずれかを忘れた場合、効果はなく、何も起こらないので「git commit」を繰り返し実行します。変更されました。
(git commitを実行して)事前コミットスクリプトを1回実行すると、ファイル.permissionsが作成されます。リポジトリに追加できますが、プリコミットスクリプトの最後に何度も追加する必要はないと思います。しかし、それは痛くない、と思います(希望)。
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"
さて、これから何を得るのでしょうか?
.permissionsファイルはgitリポジトリの最上位にあります。ファイルごとに1行あります。ここに私の例の先頭を示します。
$ 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
このアプローチに関するコメントでは、ポスターの1人が、同じユーザー名でしか機能しないと文句を言っています。技術的には正しいですが、修正するのは非常に簡単です。チェックアウト後のスクリプトには2つのアクションがあり、
# Set the file permissions
chmod $PERMISSIONS $FILE
# Set the file owner and groups
chown $USER:$GROUP $FILE
だから私は最初のものだけを保持している、それは私が必要とするすべてです。 Webサーバー上のユーザー名は確かに異なりますが、さらに重要なことは、rootでない限りchownを実行できないことです。ただし、「chgrp」を実行できます。それを使用する方法は十分に明白です。
最も広く受け入れられているこの投稿の最初の回答では、提案はgit-cache-metaを使用することです。このスクリプトは、ここでのプリ/ポストフックスクリプトと同じ作業を行っています(git ls-files
からの出力の解析)。これらのスクリプトは私にとって理解しやすく、git-cache-metaコードはかなり複雑です。 git-cache-metaをパスに保持し、それを使用する事前コミットスクリプトと事後チェックアウトスクリプトを記述することができます。
ファイル名のスペースは、Omidの両方のスクリプトの問題です。チェックアウト後のスクリプトでは、次のようなエラーが表示された場合、ファイル名にスペースが含まれていることがわかります。
$ 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
私はそのためのソリューションをチェックしています。うまくいくように見えるものがありますが、私は1つのケースでしかテストしていません
#!/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
許可情報は一度に1行なので、IFSを$に設定し、改行のみが新しいものとして認識されるようにします。
IFS環境変数を以前の状態に戻すことは非常に重要だと読みました! $を唯一の区切り文字として残すと、シェルセッションがうまくいかない理由がわかります。
コミット前/チェックアウトのオプションは、「mtree」(FreeBSD)または「fmtree」(Ubuntu)ユーティリティを使用することです。このユーティリティは、「ファイル階層を仕様と比較し、ファイル階層の仕様を作成するか、仕様。"
デフォルトセットは、flags、gid、link、mode、nlink、size、time、type、およびuidです。これは、-kスイッチを使用して特定の目的に適合させることができます。
@Omid Ariyanの答えに加えて、ディレクトリのアクセス許可があります。これを彼のpre-commit
スクリプトのfor
ループのdone
の後に追加します。
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
これにより、ディレクトリのアクセス許可も保存されます。
FreeBSD 11.1を実行しています。freebsdjail仮想化の概念により、オペレーティングシステムが最適になります。私が使用している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;
何らかの理由でスクリプトを再作成する必要がある場合、.permissionsファイルの出力は次の形式である必要があります。
.gitignore;644;0;0
Root:wheelに644権限が付与された.gitignoreファイルの場合
Statオプションにいくつかの変更を加える必要があることに注意してください。
楽しい、
.permissions
ファイルの形式を実行可能chmod
ステートメントに変更し、-printf
パラメーターをfind
に使用することにより、他の回答を改善できます。簡単な.git/hooks/pre-commit
ファイルを次に示します。
#!/usr/bin/env bash
echo -n "Backing-up file permissions... "
cd "$(git rev-parse --show-toplevel)"
find . -printf 'chmod %m "%p"\n' > .permissions
git add .permissions
echo done.
...そして、ここに簡略化された.git/hooks/post-checkout
ファイルがあります:
#!/usr/bin/env bash
echo -n "Restoring file permissions... "
cd "$(git rev-parse --show-toplevel)"
. .permissions
echo "done."
他のツールがこれらのスクリプトを既に構成している可能性があるため、それらを一緒にマージする必要がある場合があることに注意してください。たとえば、post-checkout
コマンドを含むgit-lfs
スクリプトは次のとおりです。
#!/usr/bin/env bash
echo -n "Restoring file permissions... "
cd "$(git rev-parse --show-toplevel)"
. .permissions
echo "done."
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on you
r path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-checkout.\n"; exit 2; }
git lfs post-checkout "$@"