Programming

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

procodes 2020. 2. 20. 23:39
반응형

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


?를 사용하여 웹 사이트를 배포 할 수 git push있습니까? 서버 측에서 git hooks사용 하여 수행 할 수있는 직감이 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 " 만으로 웹 사이트 코드를 배포 할 수있게되었습니다 .

작성자의 업데이트 후 스크립트는 한 줄로되어 있으며 다른 솔루션과 마찬가지로 Git 저장소를 숨기려면 .htaccess 구성이 필요하지 않습니다.

Amazon EC2 인스턴스에 배포하는 경우 몇 가지 걸림돌이 있습니다.

1) 기본 목적지 저장소를 작성하기 위해 sudo를 사용하는 경우 저장소의 소유자를 ec2-user로 변경해야합니다. 그렇지 않으면 푸시가 실패합니다. ( "chown ec2-user : ec2-user repo를 시도하십시오 .")

2) amazon-private-key .pem 의 위치를 / etc / ssh / ssh_config에서 IdentityFile 매개 변수로 또는 ~ / .ssh / config를 사용하여 미리 구성하지 않으면 "[ 호스트] - 호스트 이름 - IdentityFile이 - 사용자 "레이아웃 설명 여기 ...

...하지만 호스트가 ~ / .ssh / config에 구성되어 있고 HostName과 다른 경우 Git 푸시가 실패합니다. (아마도 Git 버그 일 것입니다)


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

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

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

이것은 체크인 된 모든 파일을 복사합니다. rsync는 서버에 설치된 ssh를 사용합니다.

서버에 설치 한 소프트웨어가 적을수록 더 안전하고 구성을 관리하고 문서화하는 것이 더 쉽습니다. 또한 서버에 완전한 git clone을 유지할 필요가 없습니다. 모든 것을 올바르게 보호하는 것이 더 복잡해집니다.


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

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

내 응용 프로그램에이라는 실행 파일로 해당 줄이 deploy있습니다.

배포를하고 싶을 때 입력 ./deploy myserver mybranch합니다.


내가하는 방법은 배포 서버에 변경 사항을 적용하는 베어 Git 저장소가 있다는 것입니다. 그런 다음 배포 서버에 로그인하여 실제 웹 서버 문서 디렉토리로 변경하고 git pull을 수행하십시오. 나는 이것을 자동으로 시도하기 위해 후크를 사용하지 않는다. 그것은 가치보다 더 문제가있는 것처럼 보인다.


Git 2.3에 추가 된 receive.denyCurrentBranch 업데이트 가 가능합니다.

서버 저장소에 설정하고 작업 트리가 깨끗하면 업데이트합니다.

push-to-checkout태어나지 않은 가지갈고리와 처리로 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 디렉토리를 포함합니다. 사용자에게 제공 할 수 없는지 확인하고 싶을 것입니다.
  • 배포하는 동안 사용자는 이전 버전의 일부 파일과 새 버전의 파일 또는 절반으로 작성된 파일로 인해 일관성이없는 상태로 사이트를 일시적으로 만날 수 있습니다. 이것이 프로젝트에 문제가된다면, 배포 후 배포는 적합하지 않을 것입니다.
  • 프로젝트에 "빌드"단계가 필요한 경우 아마도 githook을 통해 명시 적으로 설정해야합니다.

그러나 이러한 모든 사항은 Git의 범위를 벗어나므로 외부 코드로 처리해야합니다. 따라서 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와 다릅니다)


배포 시나리오

이 시나리오에서는 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( source )를 추가하여 외부에서 폴더를 숨기십시오 .

    RedirectMatch 404 /\..*$


배포를 관리하기 위해 capistrano사용 합니다. 준비 서버에 배포하기 위해 capistrano를 빌드 한 다음 모든 서버와 rsync를 실행합니다.

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

Capistrano를 사용하면 버그 발생시 쉽게 롤백 할 수 있습니다

cap deploy:rollback
cap deploy:start_rsync

Giddyup 은 언어에 구애받지 않는 just-add-water git hook으로 git push를 통한 배포를 자동화합니다. 또한 웹 서버 재시작, 캐시 예열 등을위한 사용자 정의 시작 / 정지 후크를 가질 수 있습니다.

https://github.com/mpalmer/giddyup

예제를 확인하십시오 .


서버에 두 개의 사본이 있어야합니다. 푸시 / 풀 할 수있는 베어 카피로, 완료되면 변경 사항을 푸시 한 다음 웹 디렉토리에 복제하고 매일 웹 디렉토리에서 git pull을 업데이트하도록 cronjob을 설정합니다. 그래서.


커밋이 "안정된"브랜치라고 말하면 변경 사항을 가져와 PHP 사이트에 적용하는 git hook을 설정할 수 있습니다. 가장 큰 단점은 문제가 발생하면 많은 통제력을 갖지 못하고 테스트에 시간이 추가된다는 것입니다.하지만 트렁크 분기를 안정적인 분기로 병합하여 알기 위해 얼마나 많은 작업이 포함되는지 알 수 있습니다 얼마나 많은 갈등이 발생할 수 있습니다. 한 사이트 만 실행하려는 경우가 아니라면 사이트 특정 파일 (예 : 구성 파일)을 주시하는 것이 중요합니다.

또는 대신 사이트에 변경 사항을 적용 해 보셨습니까?

git hooks에 대한 정보는 githooks 문서를 참조하십시오 .


나는 기독교인 해결책을 한다.

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 아카이브를 추출합니다.
  • 서버로 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은 자동으로 프로젝트 파일을 업로드합니다.

문안 인사


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

모든 개발자가 속한 유닉스 그룹이 있는지 확인하고 해당 그룹에 .git 저장소의 소유권을 부여하십시오.

  1. 서버 저장소의 .git / config에서 sharedrepository = true로 설정하십시오. 이것은 커밋 및 배포에 필요한 여러 사용자를 허용하도록 git에 지시합니다.

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


https://github.com/jesalg/SlimJim- 자동으로 저장소에서 새 업데이트를 가져 오는 기본 배포 도구를 만들었습니다. 기본적으로 github post-receive-hook을 듣고 프록시를 사용하여 업데이트 스크립트.


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

배포 솔루션 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은 저장소의 일부이며 커밋에 의해 제거 된 파일 만 제거합니다. Deployment Solution 2보다 빠릅니다.

DEPLOY SOLUTION 2는 저장소에 추가되었는지 여부에 관계없이 서버 측에 추가 된 프로덕션 디렉토리에서 새 파일을 제거한다는 이점이 있습니다. 항상 repo의 깨끗한 속임수입니다. Deployment Solution 1보다 느립니다.

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



반응형