1. 배포 개요
• 기본 개념: 로컬에서 Git에 push하면 서버의 Bare Repository에 코드가 업데이트되고, Git Hook(주로 post-receive)이 실행되어 최신 코드가 지정한 배포 디렉토리(DEPLOY_DIR)로 복사됩니다.
• GIT_DIR: Git의 버전 관리 데이터가 저장되는 Bare Repository의 경로
• DEPLOY_DIR: 실제 웹 서버나 애플리케이션이 실행되는 디렉토리
2. 서버 설정
2.1 Bare Repository 생성
ssh youruser@server.example.com
cd /your/path/repo # 실제 경로 대신 /your/path 사용 (보안상)
mkdir myapp.git && cd myapp.git
git init --bare
주의: 실제 서버의 경로, 사용자명, IP 등은 환경에 맞게 수정하세요.
2.2 post-receive Git Hook 설정
- 스크립트 작성 위치:
/your/path/repo/myapp.git/hooks/post-receive
- 예시 스크립트:
#!/bin/bash
# 실제 배포될 디렉토리 (예: /var/www/myapp 대신 /your/path/deploy)
DEPLOY_DIR="/your/path/deploy"
# Bare Repository 경로
GIT_DIR="/your/path/repo/myapp.git"
echo "Deploying application..."
# 지정한 브랜치의 최신 코드 체크아웃 (브랜치명은 master 또는 main 사용)
git --work-tree=$DEPLOY_DIR --git-dir=$GIT_DIR checkout -f master
# 필요한 경우 권한 설정 (사용자와 그룹은 환경에 맞게 수정)
chown -R youruser:yourgroup $DEPLOY_DIR
chmod -R 755 $DEPLOY_DIR
# 서비스 재시작 (예: Node.js, Nginx 등; 필요 시 활성화)
# systemctl restart nginx
echo "Deployment completed!"
- 실행 권한 부여:
chmod +x /your/path/repo/myapp.git/hooks/post-receive
3. 로컬 설정 및 배포
3.1 원격 저장소 추가
• SSH 설정 (예시):
vi .ssh/config
Host oneline
HostName [서버_IP] # 예: myserver or 192.168.0.01 → 환경에 맞게 수정
User youruser # 실제 사용자명
IdentityFile /your/path/ssh-key.key # SSH 키 파일 경로 (민감정보이므로 공개 시 수정)
• 원격 저장소 추가 명령어:
git remote add production oneline:/your/path/repo/myapp.git
또는 SSH 프로토콜을 명시할 경우:
git remote add production ssh://youruser@myserver/your/path/repo/myapp.git
3.2 코드 배포
• 배포 명령어: git push production master
참고: 로컬 브랜치명과 post-receive 스크립트의 checkout 대상 브랜치가 일치해야 합니다. 만약 로컬 브랜치가 master인데 스크립트는 main을 checkout하도록 되어 있다면 오류가 발생하므로 둘 중 하나를 일치시켜야 합니다.
기존대로 push 하셨을 때, 기존의 리모트 저장소로만 가게 하려면 여기까지만 하시면 되고 push 하셨을 때 자동 배포 + 기존 리모트 저장소에도 commit이 저장되었으면 한다면 아래 설정도 추가로 해주시면 됩니다.
4. 여러 Push URL 설정 (하나의 리모트에 여러 URL)
• 목적: 한 번의 push로 GitHub와 production 서버 등 여러 원격 저장소에 동시에 변경사항을 전달할 수 있습니다.
• 예시 – 원격 저장소 변경:
- 잘못된 URL 삭제:
git remote set-url --delete origin ssh://oneline:/your/path/repo/myapp.git
- 올바른 URL 추가:
git remote set-url --add origin oneline:/your/path/repo/myapp.git
• 최종 출력 예시 (git remote -v):
origin https://github.com/youraccount/yourrepo.git (fetch)
origin https://github.com/youraccount/yourrepo.git (push)
origin oneline:/your/path/repo/myapp.git (push)
production oneline:/your/path/repo/myapp.git (fetch)
production oneline:/your/path/repo/myapp.git (push)
5. 특정 이슈 발생 시 조치 방법
예기치 않은 문제나 오류가 발생할 때, 아래와 같은 점검 및 조치 방법을 참고하세요.
5.1 브랜치 불일치 오류
• 문제:
remote: error: pathspec 'main' did not match any file(s) known to git
• 원인: 로컬에서는 master 브랜치로 push했는데, post-receive 스크립트가 main 브랜치를 checkout하려고 할 때 발생.
• 조치 방법:
• 옵션 1:
post-receive 스크립트의 브랜치명을 master로 수정: git --work-tree=$DEPLOY_DIR --git-dir=$GIT_DIR checkout -f master
• 옵션 2:
로컬 브랜치명을 main으로 변경 후 push:
git branch -m master main
git push production main
5.2 권한 문제 (Permission Denied)
• 문제: 배포 후 웹 서버가 코드를 읽지 못하거나 실행에 문제가 발생할 경우.
• 조치 방법:
• 스크립트 내의 chown 및 chmod 명령어로 DEPLOY_DIR의 소유자와 권한을 올바르게 설정했는지 확인하세요.
• 필요 시, 서버의 사용자 권한과 그룹 정보를 다시 한 번 점검하고 수정합니다.
• 예시:
chown -R youruser:yourgroup $DEPLOY_DIR
chmod -R 755 $DEPLOY_DIR
5.3 post-receive 스크립트 미실행 또는 오류 발생
• 문제: Git push 후에도 코드 배포가 제대로 이루어지지 않음.
• 조치 방법:
• 스크립트에 로그를 남겨 어디서 오류가 발생하는지 확인합니다.
echo "Deploying application..." >> /your/path/deploy/deploy.log
• 스크립트가 실행 권한을 가지고 있는지 확인:
chmod +x /your/path/repo/myapp.git/hooks/post-receive
• 스크립트 내 명령어 실행 시 경로가 올바른지, 그리고 필요한 도구(git, chown 등)가 설치되어 있는지 점검합니다.
5.4 SSH 연결 및 원격 URL 문제
• 문제: push 시 SSH 연결 오류나 원격 저장소 URL 문제 발생.
• 조치 방법:
• 로컬의 ~/.ssh/config 파일 설정을 재확인하여 올바른 서버 주소와 키 파일이 사용되고 있는지 확인합니다.
• git remote -v 명령으로 등록된 URL이 정확한지, 불필요한 추가 URL이 없는지 점검하고 필요시 삭제 또는 수정합니다.
• 원격 URL을 수정하는 방법:
git remote set-url --delete origin 잘못된_URL
git remote set-url --add origin 올바른_URL
6. 결론
위와 같이 설정하면, 로컬에서 git push production master (또는 main) 명령어를 실행할 때 자동으로 서버에 배포되며, Git Hook(post-receive)을 통해 최신 코드가 지정된 배포 디렉토리로 복사되어 서비스가 재시작됩니다.
특정 이슈(브랜치 불일치, 권한 문제, 스크립트 오류, SSH 연결 문제 등) 발생 시 위 조치 방법을 참고하여 문제를 해결할 수 있습니다.
이로써 Git Push를 통한 자동 배포 설정 및 문제 발생 시의 대응 방법을 정리해 보았습니다.
- 해당 글에는 오류가 있을 경우의 롤백에 대한 처리가 없습니다.
- 간단한 배포에 대한 처리만 있는 내용으로 저의 경우 혼자 사용하는 디코봇 서버에 대해 처리해두었고, forever를 사용하여 변경사항에 대해 자동으로 감지하게 해두어서 pull 이후의 다른 처리는 주석되어있습니다.