code

Git으로 파일 권한 유지

codestyles 2020. 8. 22. 08:56
반응형

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


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

The default set are flags, gid, link, mode, nlink, size, time, type, and uid. This can be fitted to the specific purpose with -k switch.


I am running on FreeBSD 11.1, the freebsd jail virtualization concept makes the operating system optimal. The current version of Git I am using is 2.15.1, I also prefer to run everything on shell scripts. With that in mind I modified the suggestions above as followed:

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;

If for some reason you need to recreate the script the .permissions file output should have the following format:

.gitignore;644;0;0

For a .gitignore file with 644 permissions given to root:wheel

Notice I had to make a few changes to the stat options.

Enjoy,


One addition to @Omid Ariyan's answer is permissions on directories. Add this after the for loop's done in his pre-commit script.

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

This will save directory permissions as well.


We can improve on the other answers by changing the format of the .permissions file to be executable chmod statements, and to make use of the -printf parameter to find. Here is the simpler .git/hooks/pre-commit file:

#!/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.

...and here is the simplified .git/hooks/post-checkout file:

#!/usr/bin/env bash

echo -n "Restoring file permissions... "

cd "$(git rev-parse --show-toplevel)"

. .permissions

echo "done."

Remember that other tools might have already configured these scripts, so you may need to merge them together. For example, here's a post-checkout script that also includes the git-lfs commands:

#!/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 "$@"

참고URL : https://stackoverflow.com/questions/3207728/retaining-file-permissions-with-git

반응형