Git으로 파일 권한 유지

.NET에서 git repo를 만들어 내 웹 서버의 버전 관리에 설명 된대로 내 웹 서버의 버전을 제어하고 싶습니다 /var/www directory. 내 희망은 개발 서버에서 github로 웹 콘텐츠를 푸시하고 프로덕션 서버로 가져 와서 하루 종일 풀에서 보낼 수 있기를 바랍니다.

분명히 내 계획의 꼬임은 Git이 파일 권한을 존중하지 않는다는 것입니다. 하지만 내 서버가 동일하게 구성되어 있음을 알고 권한을 강제로 전파하려는 경우 옵션이 있습니까? 아니면 내가하려는 일에 접근하는 더 쉬운 방법이 있습니까?



답변

git-cache-meta“SO 질문에서 언급 ? 자식 – 어떻게 파일이 있어야한다 생각 자식 파일 권한을 복구하는 “(그리고 자식 자주 묻는 질문 ) 더 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

그래서 당신은:

  • repo를 번들로 묶고 관련 파일 권한을 저장하십시오.
  • 이 두 파일을 원격 서버에 복사하십시오.
  • 거기에 저장소를 복원하고 권한을 적용하십시오.

답변

Git은 소프트웨어 개발을 위해 만들어진 버전 제어 시스템이므로 전체 모드 및 권한 집합에서 실행 가능한 비트 (일반 파일의 경우) 및 심볼릭 링크 비트 만 저장합니다. 전체 권한을 저장하려면 git-cache-meta( VonC에서 언급 ) 또는 Metastore ( etckeeper에서 사용 ) 와 같은 타사 도구가 필요합니다 . 또는 IIRC가 git을 백엔드로 사용 하는 IsiSetup 을 사용할 수 있습니다 .

참조 인터페이스, 프론트 엔드 및 도구 힘내 위키 페이지.


답변

이것은 꽤 늦었지만 다른 사람들에게 도움이 될 수 있습니다. 내 저장소에 두 개의 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 파일을 커밋에 추가합니다.

두 번째 후크는 “체크 아웃”할 때 호출되며 .permissions 파일의 파일 목록을 살펴보고 해당 파일의 소유권과 권한을 복원합니다.

  • sudo를 사용하여 커밋 및 체크 아웃을 수행해야 할 수도 있습니다.
  • 사전 커밋 및 사후 체크 아웃 스크립트에 실행 권한이 있는지 확인합니다.

답변

지금 당장이 문제를 겪고 계신다면, 저는 오늘 그것을 겪었고 이것이 어디에 있는지 요약 할 수 있습니다. 아직 시도하지 않았다면 여기에 몇 가지 세부 정보가 도움이 될 수 있습니다.

@Omid Ariyan의 접근 방식이 가장 좋은 방법이라고 생각합니다. 사전 커밋 및 사후 체크 아웃 스크립트를 추가합니다. Omid가하는 것과 정확히 같은 이름을 지정하는 것을 잊지 말고 실행 가능하게 만드는 것을 잊지 마십시오. 둘 중 하나를 잊어 버리면 효과가없고 “git commit”을 계속 실행하여 아무 일도 일어나지 않는 이유를 궁금해합니다. 🙂 또한 웹 브라우저에서 잘라내어 붙여 넣는 경우 따옴표와 틱이 표시되지 않도록주의하십시오. 변경.

git commit을 실행하여 pre-commit 스크립트를 한 번 실행하면 .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 repo의 최상위 수준에 있습니다. 파일 당 한 줄이 있으며 여기에 내 예제의 맨 위가 있습니다.

$ 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

이 접근 방식에 대한 의견에서 한 포스터는 동일한 사용자 이름으로 만 작동하며 기술적으로는 사실이지만 고치는 것은 매우 쉽다고 불평합니다. 체크 아웃 후 스크립트에는 2 개의 작업 부분이 있습니다.

# Set the file permissions
chmod $PERMISSIONS $FILE
# Set the file owner and groups
chown $USER:$GROUP $FILE

그래서 나는 첫 번째 것만 유지하고 있습니다. 그게 내가 필요한 전부입니다. 웹 서버의 사용자 이름은 실제로 다르지만 더 중요한 것은 루트가 아니면 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

나는 그것에 대한 해결책을 확인하고 있습니다. 작동하는 것처럼 보이지만 한 가지 경우에만 테스트했습니다.

#!/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 환경 변수를 원래대로 설정하는 것이 매우 중요하다는 것을 읽었습니다! $를 유일한 구분자로 남겨두면 쉘 세션이 왜 잘못 될 수 있는지 알 수 있습니다.


답변

.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 "$@"


답변

사전 커밋 / 사후 체크 아웃에서 옵션은 “파일 계층 구조를 사양과 비교하거나, 파일 계층 구조에 대한 사양을 생성하거나, 사양.”

기본 세트는 flags, gid, 링크, 모드, nlink, 크기, 시간, 유형 및 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;

어떤 이유로 스크립트를 다시 만들어야하는 경우 .permissions 파일 출력은 다음 형식이어야합니다.

.gitignore;644;0;0

root : wheel에 644 권한이 부여 된 .gitignore 파일의 경우

통계 옵션을 몇 가지 변경해야했습니다.

즐겨,