U E D R , A S I H C RSS

Pragmatic Version Control WithCVS/Getting Started

1. Getting Started

1.1. Installing CVS

CVS서버 설치는 알아서 잘해라. -_-; 리눅스에서는 패키지로 설치하면 되고, 윈도우에서는 알아서 받아서 설치하면 된다. 이미 서버가 있으면 더 좋다. 내 경우에는 데비안 리눅스를 사용하는 관계로 apt-get install cvs로 간단히 설치를 끝냈다.

1.2. Creating a Repository

현재 우리는 테스트용으로 CVS를 쓰기 때문에 CVS의 저장소를 임시로 만들 필요가 있다.
CVS저장소를 만드는 명령은 다음과 같다.
~cpp 
Unix: cvs -d ~/sandbox init                     // 나의 경우에는 /home/CVSHOME 로 지정하였다.
Wind: cvs -d d:sandbox init

1.3. CVS Commands

CVS클라이언트는 현재 우리가 쓰는 커맨드 형태의 클라이언트도 있지만, GUI형태의 TortoiseCVS, WinCVS등도 있다. (sourceforge.net에서 확인) 또한 IDE 자체가 CVS 클라이언트의 기능을 하는 것들도 있다. (ex. eclipse, dev-cpp)

1.4. Creating a Simple Project

간단한 프로젝트를 CVS상에 만들자. 예제는 소스로 보이지는 않지만 크게 상관은 없다.

color.text
~cpp 
black
brown
red
orange
yellow
green

number.text
~cpp 
zero
one
two
three
four

이 파일이 저장된 폴더에서 다음의 명령어를 실행시킨다.
~cpp 
tmpdir#cvs -d /home/CVSHOME/ import -m " " sesame sesame initial
import는 프로젝트를 저장소에 넣을 것이라는 파라메터이다.
-m " " 프로젝트를 임포트할때 기록할 메시지임. (서드파티 코드를 사용하는 경우에 유리하다.)
sesame 저장소안에서 프로젝트의 이름
마지막 2개의 파라메터(sesame initial) tag이다.

이런과정을 마치면 CVS 루트 디렉토리에 프로젝트가 정상적으로 생성되었는지 ls 명령으로 확인해보자.

1.5. Starting to Work With a Project

이제 저장소에 저장된 파일을 로컬 작업공간에 체크아웃해보자. 이를위해서 일단 ~/work 라는 디렉토리를 구성하자.
~cpp 
#mkdir ~/work
#cd ~/work
#cvs -d /home/CVSHOME co sesame
cvs checkout: Updating sesame
U sesame/color.txt
U sesame/number.txt
~/work를 조사해서 ~/work/sesame 디렉토리에 정상적으로 저장소의 파일이 체크아웃되었다면 원본 파일을 삭제한다.

1.6. Making Changes

color.txt 의 변경
~cpp 
black
brown
red
orange
yellow
blue
purple
gray
white
color.txt를 위와 같이 변경한뒤에 프로프트에서 다음의 명령어를 사용해보자.


~cpp 
root@eunviho:~/tmpdir/sesame# cvs status color.txt 
===================================================================
File: color.txt         Status: Locally Modified

   Working revision:    1.1.1.1 Tue Aug  2 05:50:14 2005
   Repository revision: 1.1.1.1 /home/CVSHOME/sesame/color.txt,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)
상기의 status 옵션으로 확인이 가능하듯이 cvs는 자동으로 현재의 파일이 로컬 작업공간에서 수정되었다는 사실을 판단할 수 있다.


~cpp 
root@eunviho:~/tmpdir/sesame# cvs diff color.txt 
Index: color.txt
===================================================================
RCS file: /home/CVSHOME/sesame/color.txt,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 color.txt
6a7,10
> blue
> purple
> gray
> white
또한 diff 옵션을 이용해서 변경된 파일이 어떤 변경이 있었는지를 조사하여 보여주는 옵션도 존재한다.


~cpp 
root@eunviho:~/tmpdir/sesame# cvs diff --side-by-side color.txt 
Index: color.txt
===================================================================
RCS file: /home/CVSHOME/sesame/color.txt,v
retrieving revision 1.1.1.1
diff --side-by-side -r1.1.1.1 color.txt
black                                                           black
brown                                                           brown
red                                                             red
orange                                                          orange
yellow                                                          yellow
green                                                           green
                                                              > blue
                                                              > purple
                                                              > gray
                                                              > white
--side-by-side 옵션을 이용하면 지역 버전과 저장소버전을 한화면에 출력하여서 비교를 할 수 있다.

1.7. Updating the Repository

파일을 수정, UnitTest를 거치면 수정한 내용을 저장소에 저장해야할 것이다.
~cpp 
root@eunviho:~/tmpdir/sesame# cvs commit -m "고객이 4가지 색을 더 원함"
cvs commit: Examining .
/home/CVSHOME/sesame/color.txt,v  <--  color.txt
new revision: 1.2; previous revision: 1.1
변경된 프로젝트는 commit 옵션으로 체크인시키는 것이 가능하다. 이때 -m 옵션으로 변경된 사항에 대한 주석을 다는 것이 가능하며, 만약 주석을 달지 않을 경우에는 vi 에디터가 실행되면서 주석을 저장할 수 있는 파일이 열린다.
(직접해보면 안다. -_-;)


~cpp 
root@eunviho:~/tmpdir/sesame# cvs status color.txt 
===================================================================
File: color.txt         Status: Up-to-date

   Working revision:    1.2     Tue Aug  2 13:08:47 2005
   Repository revision: 1.2     /home/CVSHOME/sesame/color.txt,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)
commit 을 통해서 저장소를 체크인하고난뒤 status로 변경된 파일의 정보를 출력하면 그 결과가 반영된 것을 알 수 있다.


~cpp 
root@eunviho:~/tmpdir/sesame# cvs log color.txt 

RCS file: /home/CVSHOME/sesame/color.txt,v
Working file: color.txt
head: 1.2
branch:
locks: strict
access list:
symbolic names:
        initial: 1.1.1.1
        sesame: 1.1.1
keyword substitution: kv
total revisions: 3;     selected revisions: 3
description:
----------------------------
revision 1.2
date: 2005-08-02 13:16:58 +0000;  author: sapius;  state: Exp;  lines: +4 -0
고객이 4가지 색을 더 원함
----------------------------
revision 1.1
date: 2005-08-02 05:50:14 +0000;  author: sapius;  state: Exp;
branches:  1.1.1;
Initial revision
----------------------------
revision 1.1.1.1
date: 2005-08-02 05:50:14 +0000;  author: sapius;  state: Exp;  lines: +0 -0
 
=============================================================================
log옵션을 통해서 특정파일이 어떤 식으로 변경이 되었는지를 알 수 있다.

1.8. When Worlds Collide

이제 한개의 파일을 두사람이 동시에 변경할때 생기는 상황에대해서 살펴보자.
이러한 경우를 살피기 위해서 기존의 sesame 이라는 디렉토리이외의 공간에 저장소에 저장된 sesame을 받아야한다.
~cpp 
root@eunviho:~/tmpdir# cvs -d /home/CVSHOME/ co -d aladdin sesame
cvs checkout: Updating aladdin
U aladdin/color.txt
U aladdin/number.txt

이렇게하면 디렉토리에
~cpp 
root@eunviho:~/tmpdir# ll
total 8
drwxr-xr-x  3 root root 4096 2005-08-02 22:23 aladdin
drwxr-xr-x  3 root root 4096 2005-08-02 22:08 sesame
과 같이 동일한 저장소의 프로젝트가 서로다른 디렉토리의 로컬 작업공간을 할당받았다는 것을 알 수 있다.

sesame/number.txt
~cpp 
root@eunviho:~/tmpdir# vi sesame/number.txt
zero
one
two
three
four
five
six
상기와 같이 변경한 파일을 체크인 시킨다.
~cpp 
root@eunviho:~/tmpdir/sesame# cvs commit -m "숫자가 더 필요했다."
cvs commit: Examining .
/home/CVSHOME/sesame/number.txt,v  <--  number.txt
new revision: 1.2; previous revision: 1.1
sesame 폴더에 받아진 파일을 변경하여 체크인 시켰기 때문에 이제 aladdin 폴더에 존재하는 파일들은 더이상 최신 버전이 아니다.


~cpp 
root@eunviho:~/tmpdir/aladdin# cvs status number.txt 
===================================================================
File: number.txt        Status: Needs Patch

   Working revision:    1.1.1.1 Tue Aug  2 05:50:14 2005
   Repository revision: 1.2     /home/CVSHOME/sesame/number.txt,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)
상기와 같이 확인을 해보면 aladdin/number.txt 는 체크아웃을 통해서 저장소의 소스와 동기화를 해주어야한다는 상태를 나타내고 있다.

최신 버전이 아닌 로컬 작업공간의 내용과 저장소의 내용을 비교한다
~cpp 
root@eunviho:~/tmpdir/aladdin# cvs diff -rHEAD number.txt     
Index: number.txt
===================================================================
RCS file: /home/CVSHOME/sesame/number.txt,v
retrieving revision 1.2
retrieving revision 1.1.1.1
diff -r1.2 -r1.1.1.1
6,7d5
< five
< six
-rHEAD는 현재의 branches에 존재하는 가장 최신버전의 것과 비교하는 옵션이다. 만약 이 옵션이 없다면 cvs는 현재 받아진 지역 버전과 동일한 저장소상에 기록된 소스와 비교를 한다.
~cpp 
root@eunviho:~/tmpdir/aladdin# cvs diff number.txt 
저장소상의 aladdin 과 동일한 버전의 number.txt는 전혀 변화가 없었기 때문에 출력되는 내용이 없다.

저장소의 최신버전의 내용을 로컬에 반영하기
~cpp 
root@eunviho:~/tmpdir/aladdin# cvs update
cvs update: Updating .
U number.txt
반영되는 파일은 오로지 최신버전의 파일이 저장소에 존재할 경우만이다. 그렇지 않으면 파일은 다시 받을 필요가 없기 때문에 받지 않는다.

1.9. Conflict Resolution

다음과 같이 변경을 해서 동시에 두사람이 파일의 수정작업을 하는 경우를 가정해보자.

sesame/number.txt
~cpp 
root@eunviho:~/tmpdir# vi sesame/number.txt 
ZERO
one
two
three
four
five
six

sesame/number.txt
~cpp 
root@eunviho:~/tmpdir# vi aladdin/number.txt 
zero
one
two
three
four
five
SIX

우선 aladdin 의 파일들을 체크인한다.
~cpp 
root@eunviho:~/tmpdir/aladdin# cvs commit -m "make number six to be important"
cvs commit: Examining .
/home/CVSHOME/sesame/number.txt,v  <--  number.txt
new revision: 1.3; previous revision: 1.2

그렇게 만든뒤에 sesame의 파일을 수정한 사람이 체크인을 한다고 생각해보자.
~cpp 
root@eunviho:~/tmpdir/sesame# cvs commit -m"make number zero to be emphasized"
cvs commit: Examining .
cvs commit: Up-to-date check failed for `number.txt'
cvs [commit aborted]: correct above errors first!
상기에서 보듯이 에러를 내면서 체크인하지 못한다.

이 경우는 동시에 수정이 일어나서 저장소의 최신버전이 반영되지 못했기 때문에 발생한 것이다.
우선은 다음처럼 해보자.
~cpp 
root@eunviho:~/tmpdir/sesame# cvs update
cvs update: Updating .
RCS file: /home/CVSHOME/sesame/number.txt,v
retrieving revision 1.2
retrieving revision 1.3
Merging differences between 1.2 and 1.3 into number.txt
M number.txt

sesame/number.txt의 내용을 확인해보자
~cpp 
root@eunviho:~/tmpdir/sesame# vi number.txt 
ZERO
one
two
three
four
five
SIX
상기에서 보듯이 cvs는 너무도 잘 변경된 부분을 판단해서 현재의 로컬 소스에 반영시켜준다.

로컬에 반영이 되었으므로
~cpp 
root@eunviho:~/tmpdir/sesame# cvs commit -m"make number zero to be emphasized"
cvs commit: Examining .
/home/CVSHOME/sesame/number.txt,v  <--  number.txt
new revision: 1.4; previous revision: 1.3
상기와 같이 정상적인 체크인이 가능하다. 물론 aladdin 폴더의 내용도 다음번 수정시에는 이와 같은 일이 발생할 것이다.

1.9.1. 박치기 - 변경 내용이 충돌하는 경우

상기의 경우에는 2가지 프로그램의 바뀐 부분이 동일한 줄에 해당하지 않기 때문에 큰 문제없이 cvs가 알아서 반영을 해주었다. 그렇나 만약 변경부분이 동일한 부분이라면 어떨까?

sesame/number.txt
~cpp 
root@eunviho:~/tmpdir# vi sesame/number.txt 
ZERO
ichi
two
three
four
five
SIX

aladdin/number.txt
~cpp 
root@eunviho:~/tmpdir# vi aladdin/number.txt 
ZERO
uno
two
three
four
five
SIX


~cpp 
root@eunviho:~/tmpdir/aladdin# cvs commit -m "users like italian word of one"
cvs commit: Examining .
/home/CVSHOME/sesame/number.txt,v  <--  number.txt
new revision: 1.5; previous revision: 1.4
.
.
root@eunviho:~/tmpdir/sesame# cvs commit -m "must be japanese of word one"
cvs commit: Examining .
cvs commit: Up-to-date check failed for `number.txt'
cvs [commit aborted]: correct above errors first!
.
.
root@eunviho:~/tmpdir/sesame# cvs update
cvs update: Updating .
RCS file: /home/CVSHOME/sesame/number.txt,v
retrieving revision 1.4
retrieving revision 1.5
Merging differences between 1.4 and 1.5 into number.txt
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in number.txt
C number.txt
3번재에서 알 수 있듯, 동일한 줄을 수정한 경우에는 충돌이 일어난다는 것을 알 수 있다.
이런경우에 rcsmerge 는 그 변경을 다음과 같이 표현한다.

sesame/number.txt
~cpp 
ZERO
<<<<<<< number.txt
ichi
=======
uno
>>>>>>> 1.5
two
three
four
five
SIX
이 경우 변경된 내용은 <<<<<<< >>>>>>> 의 가운데에 존재하는 내용이 충돌을 일으킨 부분이다.

이런일이 발생한 경우에는 어떤 일이 발생했는지 기록을 우선적으로 찾아보아야한다.
~cpp 
root@eunviho:~/tmpdir/sesame# cvs log -r1.5 number.txt 

RCS file: /home/CVSHOME/sesame/number.txt,v
Working file: number.txt
head: 1.5
branch:
locks: strict
access list:
symbolic names:
        initial: 1.1.1.1
        sesame: 1.1.1
keyword substitution: kv
total revisions: 6;     selected revisions: 1
description:
----------------------------
revision 1.5
date: 2005-08-02 13:46:44 +0000;  author: sapius;  state: Exp;  lines: +1 -1
users like italian word of one
=============================================================================
마지막 세개의 줄에는 이전에 먼저체크인 된 소스를 수정한 사람과 그와 관련된 주석, 변경된 라인의 정보가 출력된다.
이런 정보를 종합해서 이전 소스의 수정한 사람과 토의를 통해서 올바른 결과를 얻어낼 수 있다.
이 경우에는 ichi를 쓰기로 했다고 가정하자. ichi이외의 다른 부분의 나용을 모두 삭제한다. 그리고 토의 결과
two를 due로 쓰기로 했다고 하자
~cpp 
root@eunviho:~/tmpdir/sesame# vi number.txt 
ZERO
ichi
due
three
four
five
SIX
.
.
root@eunviho:~/tmpdir/sesame# cvs commit -m "one is japanese, two is italian"
cvs commit: Examining .
/home/CVSHOME/sesame/number.txt,v  <--  number.txt
new revision: 1.6; previous revision: 1.5

위와 같은 방식(느슨한 잠금)에 의해서 버전 커트롤이 가능하기 대문에 동기화로 인한 문제는 거의 발생하지 않는다.

----
PragmaticVersionControlWithCVS
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-05-27 07:09:19
Processing time 0.1021 sec