SVN(Subversion) 사용하기

SVN(Subversion) 사용하기

SVN(Subversion) 사용하기

SVN이란 여러 사람이 협업하는 프로젝트에서 소스 코드를 형상 관리하기 위한 툴이다.

아파치 소프트웨어 재단에서 개발 되었으며 아파치 라이선스를 따른다.

기본 설정 및 세팅

  • 서버/클라이언트 구조
    • 서버
      • Linux 계열은 각 배포판의 패키지 관리자를 이용하여 쉽게 설치 가능(apt, yum 등)
      • freeBSD 는 ports 또는 pkg 를 이용하여 설치 가능
      • 설치 후 Repository를 관리 할 디렉토리 생성 후 SVN 서비스 시작
    • 클라이언트
  • TCP/IP 소켓 통신
    • SVN 포트 : 3690
    • SSH 를 이용하여 통신 가능 : 22

시작하기

  1. 형상 관리 될 소스 코드(프로젝트)의 Repository 생성하기

# 현재 위치는 SVN 서버의 Repository 디렉토리 
❯ pwd 
/home/svnsvr/repos 

# svnadmin 명령어를 통해 "cal-save"라는 저장소 생성 
❯ svnadmin create --fs-type fsfs cal-save 

❯ l 
total 10 
drwxrwx--- 3 root    svnsvr 3B May 15 20:24 . 
drwxrwx--- 3 svnsvr  svnsvr 3B Mar 22 09:05 .. 
drwxr-xr-x 6 jongbin svnsvr 8B May 15 20:24 cal-save

 

  1. [옵션] SVN 프로토콜을 사용한다면 해당 repository 설정이 필요함 SSH 사용할 경우 SSH 계정을 이용하기 때문에 필요 없음
    1. 접속 계정

# Repository 설정을 위해 해당하는 저장소 하위 "conf" 디렉토리 이동 
❯ pwd 
/home/svnsvr/repos/cal-save/conf 

# passwd 파일을 수정하여 접속 계정을 설정한다.
# svnserve.conf 파일을 수정하여 passwd 파일(접속계정)을 사용할 수 있도록 주석 해제 해제한다.
❯ l 
total 35 drwxr-xr-x 2 jongbin svnsvr 6B May 15 20:24 . 
drwxr-xr-x 6 jongbin svnsvr 8B   May 15 20:24 .. -
 rw-r--r-- 1 jongbin svnsvr 1.1K May 15 20:24 authz 
-rw-r--r-- 1 jongbin svnsvr 885B May 15 20:24 hooks-env.tmpl 
-rw-r--r-- 1 jongbin svnsvr 309B May 15 20:24 passwd 
-rw-r--r-- 1 jongbin svnsvr 4.3K May 15 20:24 svnserve.conf

 

  1. [옵션] Hook 설정 혼자 시작하므로 우선 Skip
    • 예를 들어 커밋이 될 때 이메일을 송신한다던지 등 스크립트를 통해 훅 설정이 가능하다.
  2. 클라이언트에서 해당 저장소를 임포트 또는 체크아웃 하기
    • 이미 진행한 프로젝트에 대해 형상 관리를 시작할 때
      • 기본 구조 생성 후 해당 프로젝트를 trunk에 임포트 시키면 된다.
    • 처음부터 저장소에 구조를 잡고 시작할 경우
      1. 체크아웃 할 곳에서 마우스 오른쪽 클릭 후 “SVN 체크 아웃(K)…”를 눌러 해당 저장소를 불러온다.

        체크아웃
        체크아웃
      2. 기본 구조를 생성한다. 보통 trunk, branches, tags 세 디렉토리로 시작한다.
      3. 기본 구조를 SVN 추가하기를 눌러 추가한다.

        추가하기
        추가하기
      4. 커밋을 눌러 저장소에 반영한다.
        • 커밋할 때는 반드시 자세한 로그를 남겨야 한다.
    1. 저장소의 trunk 디렉토리 하위로 다시 체크아웃 하기
      • 프로젝트 디렉토리를 열었을 때 trunk, branches, tags 등 형상 관리를 사용하기 위한 구조가 보일 필요는 없다. 따라서 임포트했던 프로젝트 또는 체크아웃하여 기본 구조 디렉토리를 만들었던 디렉토리는 지우고 다시 체크 아웃을 한다.

형상 관리하기

소스파일 추가

아래와 같은 구조로 소스를 추가했다고 가정한다.

# 현재 디렉토리는 Repository의 trunk C
:\Users\jongbin\Desktop\source\cal-save-server 
C:. 
├─doc 
│ cal-save-server.wsd 
│ 
├─inc 
│ common.h
│ pool.h 
│ 
├─lib 
│ pool.cc 
│ 
└─src main.cc

 

  1. 해당 디렉토리를 SVN 컨텍스트 메뉴에서 “추가하기” 버튼을 눌러 추가한다.
  2. 프로젝트 디렉토리를 우클릭 하여 “커밋”을 누른다.
  3. 어떤 내용인지 자세히 적고 “확인”을 누른다.
로그
로그

수정 및 삭제

항상 작업 전 프로젝트를 저장소 최신본으로 만들고 작업하는 편이 좋다. 따라서 프로젝트 디렉토리를 우클릭하여 “업데이트”를 먼저 누른다.

업데이트
업데이트

우선 아래 최신 리비전의 “main.cc” 파일의 내용이다.

#include "common.h" 
#include "pool.h" 

using namespace std; 

int main(int argc, char **argv) 
{ 
    spdlog::error("test"); // 해당 라인 편집 
    
    Pool::init(); 
    
    return 0; 
}

 

여기서 8번째 줄을 편집을 할 것이고 해당 내용을 커밋할 것이이다.

#include "common.h" 
#include "pool.h" 

using namespace std; 

int main(int argc, char **argv) 
{ 
    spdlog::info("start main function <<"); // 변경
    
    Pool::init(); 
    
    return 0; 
}

 

  1. 프로젝트 디렉토리 우클릭 후 “커밋하기”를 누른다.
  2. 수정 및 삭제된 내용을 포함하여 상세 내역을 작성한다.
커밋하기
커밋하기
  • 삭제가 필요한 경우
    • 저장소 및 로컬 모두 삭제
      • SVN 메뉴에서 “삭제”를 클릭하여 삭제한다.
      • 삭제된 내용을 “커밋”하여 저장소에 반영한다.
    • 저장소만 삭제
      • SVN 메뉴에서 “버전 관리에서 삭제하고 무시 목록에 추가”
      • 해당 내용을 “커밋”하여 저장소에 반영한다.

충돌 상황

충돌 상황이란 같은 리비전의 소스 파일을 서로 다른 작업자가 서로 다르게 수정했을 때 일어나는 상황으로, 서로 다르게 수정한 부분을 합의하여 하나의 파일로 만들어주는 과정이 필요하다.

충돌 상황을 가정하기 위해 같은 프로젝트의 저장소를 하나 더 체크아웃 한 후 같은 파일을 서로 다르게 수정한다.

체크아웃
체크아웃

작업자 0의 작업 사본 : cal-save-server
작업자 1의 작업 사본 : cal-save-server(conflict test)

작업자 0과 1 모두 “end main function” 이라는 로그를 남기는 소스를 추가하였다고 가정한다. 하지만 작업자 0과 1의 소스 내용이 아래와 같이 사소하게 다른 경우가 발생할 수 있다.

작업자 0의 소스 내용

#include "common.h" 
#include "pool.h" 

using namespace std; 

int main(int argc, char **argv) 
{ 
    spdlog::info("start main function <<"); 
    
    Pool::init(); 
    
    spdlog::info("end main function <<"); 
    
    return 0; 
}

 

작업자 1의 소스 내용

#include "common.h" 
#include "pool.h" 

using namespace std; 

int main(int argc, char **argv) 
{ 
    spdlog::info("start main function <<"); 
    
    Pool::init(); 
    
    spdlog::error("end main function <<");
    
    return 0; 
}

 

작업자 0과 1의 차이점은 해당 로그를 info로 처리하느냐 error로 처리하느냐의 차이

작업자 0은 해당 내용을 커밋하고 저장소에 반영했다. 그 후 작업자 1이 커밋을 하려고 보니까 최신의 리비전이 아니라 아래와 같은 오류가 발생했다.

커밋 실패
커밋 실패

업데이트를 하니 충돌 상황이 발생했다.

충돌 발생
충돌 발생

또한 파일들이 생성 되었다.

C:. 
│ CMakeLists.txt 
│ 
├─doc 
├─inc 
│ common.h 
│ pool.h 
│ 
├─lib
│ pool.cc 
│ 
└─src main.cc main.cc.mine main.cc.r3 main.cc.r4

 

main.cc

#include "common.h" 
#include "pool.h" 

using namespace std; 

int main(int argc, char **argv) 
{ 
    spdlog::info("start main function <<"); 
    
    Pool::init(); 
    
<<<<<<< .mine 
    spdlog::error("end main function <<"); 
    
||||||| .r3 
======= 
    spdlog::info("end main function <<"); 

>>>>>>> .r4 
    return 0; 
}

 

<<<<<<< .mine
내가 수정한 내용 (작업자 1의 내용 : error로 로그처리)
||||||| .r3
리비전 3의 내용 (해당 리비전에 아무 내용이 없었음)
=======
리비전 4의 내용 (작업자 0의 내용 : info로 처리 후 커밋한 내용)
>>>>>>> .r4

작업자 0과 작업자 1이 상의하여 충돌 상황을 편집하여 다시 main.cc 파일을 만들면 된다. SVN 메뉴에서 “충돌상황 편집”을 누르면 TortoiseMerge 에디터가 실행된다. 여기서 위쪽의 두 개의 서로 다른 소스파일을 갖고 아래 하나의 main.cc 파일을 만들면 된다.

TortoiseMerge
TortoiseMerge

상의 결과 main 함수가 종료되는 것은 error로 판단한다고 결론이 났으며 작업자 1의 내용으로 수정 및 커밋하기로 한다.

작업자 1의 소스 파일의 내용을 사용하기 위해 아래 물음표(?)로 된 두 줄을 선택한 후 아래 아이콘을 선택하여 하나의 파일로 병합 후 저장버튼을 누른다.

아이콘
아이콘
병합
병합

충돌 부분이 없다면 아래와 같은 팝업이 뜨고, 해결 완료 표시를 눌러주면 완료된다.

충돌 해결
충돌 해결

확장자가 .mine, .r3, r4가 없어진 것을 확인할 수 있고 해결된 내용을 커밋해주면 완료된다.

branch & tag

branch를 사용하는 목적은 아래와 같을 것이다.

  1. trunk 디렉토리에 공통된 모듈 및 레이아웃을 구성 후 사이트별로 프로젝트를 관리할 때
  2. 운영중인 trunk 소스에 기능을 추가할 때
,

%d 블로거가 이것을 좋아합니다: