programing

Git push를 사용하여 프로젝트 배포

i4 2023. 5. 11. 21:05
반응형

Git push를 사용하여 프로젝트 배포

다음을 사용하여 웹 사이트를 배포할 수 있습니까?git push저는 그것이 훅을 사용하여 공연을 하는 것과 관련이 있다고 생각합니다.git reset --hard서버 측면에서, 하지만 제가 어떻게 이것을 달성할 수 있을까요?

사이트에서 이 스크립트를 찾았는데 꽤 잘 작동하는 것 같습니다.

  1. .git 디렉터리를 통해 웹 서버로 복사
  2. 로컬 복사본에서 .git/config 파일을 수정하고 웹 서버를 원격으로 추가합니다.

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. 서버에서 .git/hooks/post-update를 이 파일로 바꿉니다(아래 답변 참조).

  4. 파일에 대한 실행 권한을 추가합니다(서버에서 다시).

    chmod +x .git/hooks/post-update
    
  5. 이제 로컬로 웹 서버에 푸시하기만 하면 작업 복사본이 자동으로 업데이트됩니다.

    git push production
    

아래 업데이트 후 파일 사용:

  1. .git 디렉터리를 통해 웹 서버로 복사
  2. 로컬 복사본에서 .git/config 파일을 수정하고 웹 서버를 원격으로 추가합니다.

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. 서버에서 .git/hooks/post-update를 아래 파일로 바꿉니다.

  4. 파일에 대한 실행 권한을 추가합니다(서버에서 다시).

    chmod +x .git/hooks/post-update
    
  5. 이제 로컬로 웹 서버에 푸시하기만 하면 작업 복사본이 자동으로 업데이트됩니다.

    git push production
    
#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update". 
git-update-server-info 
is_bare=$(git-config --get --bool core.bare) 
if [ -z "$is_bare" ]
then
      # for compatibility's sake, guess
      git_dir_full=$(cd $GIT_DIR; pwd)
      case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi 
update_wc() {
      ref=$1
      echo "Push to checked out branch $ref" >&2
      if [ ! -f $GIT_DIR/logs/HEAD ]
      then
             echo "E:push to non-bare repository requires a HEAD reflog" >&2
             exit 1
      fi
      if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
      then
             wc_dirty=0
      else
             echo "W:unstaged changes found in working copy" >&2
             wc_dirty=1
             desc="working copy"
      fi
      if git diff-index --cached HEAD@{1} >/dev/null
      then
             index_dirty=0
      else
             echo "W:uncommitted, staged changes found" >&2
             index_dirty=1
             if [ -n "$desc" ]
             then
                   desc="$desc and index"
             else
                   desc="index"
             fi
      fi
      if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
      then
             new=$(git rev-parse HEAD)
             echo "W:stashing dirty $desc - see git-stash(1)" >&2
             ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
             git-update-ref --no-deref HEAD HEAD@{1}
             cd $GIT_WORK_TREE
             git stash save "dirty $desc before update to $new";
             git-symbolic-ref HEAD "$ref"
             )
      fi 
      # eye candy - show the WC updates :)
      echo "Updating working copy" >&2
      (cd $GIT_WORK_TREE
      git-diff-index -R --name-status HEAD >&2
      git-reset --hard HEAD)
} 
if [ "$is_bare" = "false" ]
then
      active_branch=`git-symbolic-ref HEAD`
      export GIT_DIR=$(cd $GIT_DIR; pwd)
      GIT_WORK_TREE=${GIT_WORK_TREE-..}
      for ref
      do
             if [ "$ref" = "$active_branch" ]
             then
                   update_wc $ref
             fi
      done
fi

많은 잘못된 시작과 막다른 골목 끝에, 저는 마침내 이 기사 덕분에 "git push remote"만으로도 웹사이트 코드를 배포할 수 있게 되었습니다.

작성자의 업데이트 후 스크립트는 한 줄 길이에 불과하며 다른 작성자들처럼 Gitrepo를 숨기기 위해 그의 솔루션은 .htaccess 구성이 필요하지 않습니다.

Amazon EC2 인스턴스에 이 기능을 구현하는 경우 몇 가지 걸림돌이 있습니다.

sudo를 사용하여 기본 대상 저장소를 생성하는 경우, repo의 소유자를 ec2-user로 변경해야 합니다. 그렇지 않으면 푸시가 실패합니다.("chown ec2-user:ec2-user repo"를 사용해 보십시오.")

/etc/ssh/ssh_config에서 amazon-private-key.pem의 위치를 ID로 미리 구성하지 않으면 푸시가 실패합니다.파일 매개 변수 또는 "[Host] - HostName - Identity를 사용하는 ~/.ssh/config여기에 설명된 파일 - 사용자" 레이아웃...

...그러나 Host가 ~/.ssh/config에 구성되어 있고 HostName과 다른 경우 Git 푸시가 실패합니다.(그것은 아마도 Git 버그일 것입니다)

git를 서버에 설치하거나 .git 폴더를 복사하지 마십시오. git 클론에서 서버를 업데이트하려면 다음 명령을 사용할 수 있습니다.

git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project

프로젝트에서 제거된 파일을 삭제해야 할 수도 있습니다.

이렇게 하면 체크인된 모든 파일이 복사됩니다.rsync는 어쨌든 서버에 설치된 ssh를 사용합니다.

서버에 설치한 소프트웨어가 적을수록 보안이 강화되고 구성을 관리하고 문서화하는 것이 쉬워집니다. 또한 서버에 전체 git 복제본을 보관할 필요가 없습니다.모든 것을 제대로 보호하는 것이 더 복잡해질 뿐입니다.

git config --local receive.denyCurrentBranch updateInstead

Git 2.3에 추가된 다음과 같은 좋은 가능성이 있습니다. https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

서버 리포지토리에 설정하면 작업 트리가 깨끗할 경우에도 업데이트됩니다.

2.4에서는 태어나지 않은 가지의 후크와 핸들링이 추가로 개선되었습니다.

샘플 사용량:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

출력:

a
b

GitHub 발표에서 언급된 단점은 다음과 같습니다.

  • 서버에는 프로젝트의 전체 기록이 들어 있는 .git 디렉토리가 포함됩니다.여러분은 아마도 그것이 사용자들에게 제공될 수 없도록 하기를 원할 것입니다!
  • 배포하는 동안 일부 파일은 이전 버전에 있고 다른 파일은 새 버전에 있거나 반쯤 작성된 파일과 함께 사이트가 일관되지 않은 상태로 일시적으로 나타날 수 있습니다.이것이 프로젝트에 문제가 되는 경우, 푸시-투-배포는 사용자에게 적합하지 않을 수 있습니다.
  • 프로젝트에 "빌드" 단계가 필요한 경우에는 githooks를 통해 명시적으로 설정해야 합니다.

하지만 그 모든 점들은 Git의 범위 밖에 있으며 외부 코드로 처리해야 합니다.그런 의미에서, 이것은 깃 훅과 함께 궁극적인 해결책입니다.

기본적으로 필요한 것은 다음과 같습니다.

server = $1
branch = $2
git push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"

는 이 을 응용 . 실행 파일 이름은 다음과 같습니다.deploy.

그래서 배포를 수행할 때 입력합니다../deploy myserver mybranch.

배포 서버에 기본 Git 저장소를 설치하여 변경 사항을 푸시합니다.그런 다음 배포 서버에 로그인하고 실제 웹 서버 문서 디렉터리로 변경한 다음 장치 풀을 수행합니다.저는 자동으로 이 작업을 수행하기 위해 어떤 후크도 사용하지 않습니다. 그것은 가치보다 더 큰 문제인 것 같습니다.

업데이트: 현재 키 에이전트와 함께 Lloyd Moore 솔루션을 사용하고 있습니다.ssh -A ...메인 레포로 푸시한 다음 모든 기계에서 병렬로 풀링하는 것이 조금 더 빠르며 이러한 기계에서 설정이 덜 필요합니다.


여기에서는 이 솔루션을 볼 수 없습니다. 서버에 git이 설치되어 있으면 ssh를 통해 푸시하십시오.

로컬 .git/config에 다음 항목이 필요합니다.

[remote "amazon"]
    url = amazon:/path/to/project.git
    fetch = +refs/heads/*:refs/remotes/amazon/*

하지만 이봐, 그게 뭐야.amazon: " ~/.ssh/config".

Host amazon
    Hostname <YOUR_IP>
    User <USER>
    IdentityFile ~/.ssh/amazon-private-key

이제 당신은 전화할 수 있습니다.

git push amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'

(BTW: /path/to/project.git은 실제 작업 디렉토리 /path/to/project와 다릅니다.)

배포 관리를 위해 Capistrano를 사용합니다.스테이징 서버에 배포할 Capistrano를 구축한 다음 모든 서버와 Arsync를 실행합니다.

cap deploy
cap deploy:start_rsync (when the staging is ok)

카피스트라노를 사용하면 버그 발생 시 쉽게 롤백할 수 있습니다.

cap deploy:rollback
cap deploy:start_rsync

배포 시나리오의 경우

이 시나리오에서는 github/bitbucket에 코드를 저장하고 있으며 라이브 서버에 배포하려고 합니다.이 경우 다음과 같은 조합을 사용할 수 있습니다(이것은 여기에서 매우 인기 있는 답변을 리믹스한 것입니다).

  1. 위에 .git의 웹 서버에 입니다.
  2. 복사본에 .git remote add live ssh://user@host:port/folder
  3. 원격:git config receive.denyCurrentBranch ignore
  4. 원격:nano .git/hooks/post-receive다음 내용을 추가합니다.

    #!/bin/sh GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f

  5. 원격:chmod +x .git/hooks/post-receive

  6. 이제 당신은 그것을 밀고 나갈 수 있습니다.git push live

메모들

  • 이 솔루션은 이전 Git 버전에서 작동합니다(1.7 및 1.9로 테스트됨).
  • 먼저 github/bitbucket으로 푸시해야 실시간으로 일관된 응답을 얻을 수 있습니다.
  • 만약 당신이.git. 폴더를 루트에 합니다. 외부로부터 숨겨야 합니다..htaccess(소스):

    RedirectMatch 404 /\..*$

Giddup은 Git 푸시를 통해 배포를 자동화하기 위한 언어에 구애받지 않는 Just-Add-Water Git 후크입니다.또한 웹 서버 재시작, 캐시 워밍업 등을 위한 맞춤형 시작/중지 후크를 사용할 수 있습니다.

https://github.com/mpalmer/giddyup

예제를 확인하십시오.

서버에 복사본이 두 개 있어야 할 것 같습니다.작업이 완료되면 변경사항을 밀어넣을 수 있는 맨 복사본입니다. 그런 다음 이 복사본을 웹 디렉터리로 복제하고 cron 작업을 설정하여 매일 웹 디렉터리에서 git pull을 업데이트합니다.

당신은 아마도 "안정적인" 분기를 말하는 커밋이 이루어질 때 변경 사항을 당겨 PHP 사이트에 적용하는 깃 훅을 설정할 수 있습니다.큰 단점은 무언가 잘못되면 통제력이 별로 없고 테스트에 시간이 더해진다는 것입니다. 하지만 트렁크 분기를 안정적인 분기로 병합할 얼마나 많은 작업이 수반되는지 파악할 수 있습니다.하나의 사이트만 실행하려는 경우가 아니라면 사이트별 파일(예: 구성 파일)을 주시하는 것이 중요합니다.

또는 사이트에 변경 사항을 적용하는 방안을 검토해 보셨습니까?

깃 후크에 대한 자세한 내용은 깃 후크 설명서를 참조하십시오.

는 기독교인들의 해결책에 대해 생각합니다.

git archive --prefix=deploy/  master | tar -x -C $TMPDIR | rsync $TMPDIR/deploy/ --copy-links -av username@server.com:/home/user/my_app && rm -rf $TMPDIR/deploy
  • 마스터 분기를 tar로 보관합니다.
  • tar 아카이브를 시스템 temp 폴더의 deploy dir에 추출합니다.
  • rsync 변경 사항을 서버에 동기화
  • temp 폴더에서 deploy dir를 삭제합니다.

저는 더 간단한 후크 스크립트를 가진 toroid.org 의 다음 솔루션을 사용하고 있습니다.

서버:

$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/

서버에 후크를 설치합니다.

$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
GIT_WORK_TREE=/var/www/www git clean -f -d # clean directory from removed files

$ chmod +x hooks/post-receive

클라이언트에서:

$ mkdir website && cd website
$ git init
Initialized empty Git repository in /home/ams/website/.git/
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."

$ git remote add web ssh://server.example.org/home/ams/website.git
$ git push web +master:refs/heads/master

게시하려면 다음과 같이 입력하십시오.

$ git push web

웹사이트에 자세한 설명이 있습니다: http://toroid.org/ams/git-website-howto

보완적인 답변으로 대안을 제시하고자 합니다.저는 git-ftp를 사용하고 있고 그것은 잘 작동합니다.

https://github.com/git-ftp/git-ftp

사용하기 쉽고, 유형만 가능:

git ftp push

git는 자동으로 프로젝트 파일을 업로드합니다.

안부 전해요

여러 개발자가 동일한 리포지토리에 액세스하는 환경에서 다음 지침이 도움이 될 수 있습니다.

모든 dev가 속한 unix 그룹이 있는지 확인하고 해당 그룹에 .git 저장소 소유권을 부여합니다.

  1. 서버 리포지토리의 .git/config에서 공유 리포지토리 = true를 설정합니다.이 명령은 커밋 및 배포에 필요한 여러 사용자를 허용하도록 git에 지시합니다.

  2. bashrc 파일에 있는 각 사용자의 umask를 동일하게 설정합니다. 002는 좋은 시작입니다.

저는 결국 레포(https://github.com/jesalg/SlimJim )에서 새 업데이트를 자동으로 다운로드하는 기본 배포 도구를 만들었습니다. 기본적으로 이 도구는 github 사후 업데이트 후크를 수신하고 프록시를 사용하여 업데이트 스크립트를 트리거합니다.

수신 후 후크에는 두 가지 솔루션을 사용합니다.

솔루션 1 구축

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 1 

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi
done

솔루션 2 배포

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 2

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    export GIT_TEMP_DIR1=/tmp/deploy1
    export GIT_TEMP_DIR2=/tmp/deploy2
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo "GIT TEMP DIR1:  $GIT_TEMP_DIR1/"
    echo "GIT TEMP DIR2:  $GIT_TEMP_DIR2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR1; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR1/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET1/.
        rsync $GIT_TEMP_DIR1/. -v -q --delete --delete-after -av $GIT_TARGET1/.
        rm -rf $GIT_TEMP_DIR1
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR2/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET2/.
        rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/.
        rm -rf $GIT_TEMP_DIR2
    fi
done

두 솔루션 모두 이 스레드에서 사용할 수 있는 이전 솔루션을 기반으로 합니다.

BRANCH_REGEX='^${GIT_BRANCH1}을(를) 참조하십시오."master" 또는 "dev*" 문자열과 일치하는 분기 이름을 필터링하고 푸시된 분기가 일치하는 경우 작업 트리를 배포합니다.이렇게 하면 개발 버전과 마스터 버전을 다른 위치에 배포할 수 있습니다.

DEPLOY SOLUTION 1은 repo의 일부인 파일만 제거하고 커밋을 통해 제거했습니다.Deployment 솔루션 2보다 빠릅니다.

DEPLOY SOLUTION 2의 장점은 보고서에 추가되었는지 여부에 관계없이 서버 측에 추가된 프로덕션 디렉터리에서 새 파일을 제거한다는 것입니다.그것은 항상 레포를 속이고 깨끗할 것입니다.Deployment 솔루션 1보다 느립니다.

언급URL : https://stackoverflow.com/questions/279169/deploy-a-project-using-git-push

반응형