이전페이지 다음페이지 차례

5. RCS를 사용해 봅시다. (고급)

5.1 RCS에서의 버전 (버전트리)

RCS를 사용해서 자꾸 버전업(version up)을 하다 보면 한 줄로 이어서 버전이 만들어질 껍니다. 버전트리의 개념을 설명하기 전에 RCS에서의 버전 체계에 대해서 말씀드리죠. RCS파일이 처음으로 만들어지면 1.1부터 시작합니다. 그리고 다음 버전은 1.2,1.3 이렇게 소수점 이하의 숫자만 계속 늘어나게 됩니다. 결코 2.0의 파일은 만들어지지 않습니다. RCS에서는 강제적으로 버전업을 시킬 수 있는 기능을 제공합니다.

% ci -r2.0 -l exam.c

위와 같이 하면 버전 2.0으로 강제적으로 만들 수가 있습니다. 여기서 -r 은 revision을 뜻하는 옵션입니다. 위의 예제는 exam.c를 버전 2.0으로 올리고 동시에 lock도 걸라는 표시입니다. 버전이 2.0이 되고 부터는 ci를 하면 다시 2.1 -> 2.2 -> 2.3 의 순서로 버전이 증가합니다.

그렇다면 각 버전의 파일을 풀 수도 있겠군요.

% co -r1.2 -l exam.c

위와 같이 하면 exam.c가 어떻게 되어 있더라도 버전 1.2 에 해당하는 RCS 파일이 풀려나옵니다. 그냥 co -l exam.c라고만 한다면 exam.c의 가장 높은 버전이 풀려나옵니다. 만약 필요에 의해 1.2 버전을 몇 가지 고친 다음에 다시 이것을 RCS에 올린다고 가정합니다. 그럼 다음 버전은 무엇일까요? 답은 가장 높은 버전의 다음 버전입니다. 즉 2.1이 되겠군요.

그런데 한가지 논리적으로 이상하지 않나요. 다음의 버전 트리를 한번 봅시다.

+-----+     +-----+     +-----+      +-----+
| 1.1 |---->| 1.2 |---->| 2.0 |      | 2.1 |                                
+-----+     +--+--+     +-----+      +--+--+
               |                        |
               +------------------------+                   

각 2.0의 다음이 2.1인데 1.2 버전의 다음이 2.1이라니 말입니다. 완전히 할아버지 다음에 아버지 빼고 아들로 바로 내려가는 거랑 같군요. 그럼 2.0을 바꾸면 다음은 2.2가 되겠군요. 이것은 버전의 연속성이 깨어지게 되는 나쁜 결과입니다.

RCS에서는 버전의 연속성을 보장하기 위해서 branch 기능을 제공합니다. 가령 1.2를 수정한 후 이것을 다른 버전으로 다시 관리하고 싶다고 생각이 들 때 버전을 1.2.1로 저장하는 것입니다. 맨 끝의 1은 branch number를 가리킨다고 생각하시면 됩니다. 1.2.1의 첫 번째 branch 는 1.2.1.1로 시작합니다. 그러니까 앞의 1.2를 빼면 다시 버전이 1.1로 시작하는 것과 같다고 할 수가 있군요. 이것을 버전 트리로 표현한다면 아래와 같이 될 수가 있습니다.

+-----+     +-----+     +-----+      +-----+      +-----+
| 1.1 |---->| 1.2 |---->| 2.0 |----->| 2.1 |----->| 2.2 |
+-----+     +--+--+     +-----+      +-----+      +-----+
               |
            +--+----+     +--------+
            |1.2.1.1|---->|1.2.1.2 |
            +-------+     +--------+

버전 트리를 보니까 대충 이해가 되시죠. 그런데 또 한가지 문제가 있습니다. 뭐냐 하면 1.2.1.1 을 고쳐서 ci시키면 에러가 난다는 것입니다. 원래는 1.2.1.2 가 되어야 하는데 말입니다. 즉 아래와 같이...

%ci -l exam.c
RCS/exam.c,v <- exam.c
ci error: multiple revisions locked by raxis; please specify one

흠.. 이게 무슨 날벼락 같은 소리... lock이 여러개가 걸려있다니요. lock을 잘은 모르지만 하나밖에 걸지 않은 것 같은데 말입니다. 그럼 RCS/exam.c,v의 내용(윗부분)만 잠시 보기로 할까요. 문제의 답이 있기 때문이죠.

RCS/exam.c,v


head 2.0;
access;
symbols;
locks
raxis:1.2.1.1
raxis:1.2
raxis:2.0; strict;
comment @ * @;

위에 보면 locks 라는 곳이 보이십니까? 흠... 알게 모르게 lock이 3군데나 걸려 있군요. 위에서 strict라고 쓰여진 부분은 저도 아직 잘은 모르지만 짐작컨대 아마도 버전 트리가 형성될 가망성이 있는 부분을 가리키고 있는 것 같습니다. 제가 여러 가지 테스트를 거쳐서 얻은 결론은 strict가 있는 버전을 중심으로 버전 트리가 형성된다는 것입니다. 1.2 에 만약 strict가 있다면 이것은 1.2.2 (두번째 branch)가 형성될 수 있다는 말이 됩니다.

흠... 그럼 strict 라는 것이 1.2.1.1에 오게 하면 되겠군요. 맞습니다. 결론은 2.0과 1.2의 lock를 해제해야 한다는 말이 되는군요. 강좌1에서 rcs란 명령어는 RCS파일의 속성을 바꾼다고 했습니다. rcs의 옵션중에 보면 -u가 있습니다. unlock 이란 뜻이 됩니다.

% rcs -u2.0 exam.c
RCS file: RCS/exam.c,v
2.0 unlocked
done

% rcs -u1.2 exam.c
RCS file: RCS/exam.c,v
1.2 unlocked
done

이제는 strict 가 1.2.1.1 에 있는 것을 보게 되실 겁니다. locks라고 불린 곳에는 strict가 있는 버전 하나만 존재해야 합니다. 나머지는 모두 unlock 시켜서 없애야 되겠군요. 이제부터는 1.2.1로부터 버전 트리가 형성됩니다. 만약 버전 2.0에서 버전 트리를 형성하고 싶으시다면 아래와 같이 하세요.

% rcs -u1.2.1 exam.c
% rcs -l2.0 exam.c

참고

사실 버전 트리 부분은 초보자가 보기엔 참 애매모호한 부분입니다. 또 lock이라는 개념 자체도 어렵죠. 죄송합니다. 더 이상 설명을 쉽게 할 수가 없네요. 그러나 버전업이 될 때 버전 트리가 형성된다는 것은 기억하고 계세요. 모든 것을 버전 트리로 이해하면 위의 것도 대충 이해가 될 겁니다.

5.2 Auto Identification 기능

이제 좀 화제를 다른 데로 돌리기로 하죠. 보통 제품을 생산을 한다면 그 제품에는 생산 날짜, 생산지 등등의 정보가 찍혀지게 되죠. RCS에서는 이와 유사한 것을 지원합니다. 즉, 소스와 목적 코드(object code)에 자신의 프로그램임을 확신시켜 주는 특별한 문자열을 삽입하게 되죠.

소스에 아래와 같은 라인을 추가해 봅시다.

static char rcsid[] = '$Id:$' ;

그럼 RCS의 ci 명령어 이후에는 다음과 같은 형태로 바뀌어져 있습니다.

static char rcsid[] = '$Id: exam.c,v 1.1
1995/10/13 14:54:09
raxis Exp raxis (줄이 길어서 분리)

생성날짜, 시간, 만든이 등등의 정보가 나와 있군요. 프로그램 내부에서 static 변수이므로 당연히 프로그램 컴파일과 함께 프로그램에 영원히(?) 내장이 되겠지요. 누가 자기꺼 훔쳐 가도 금방 알 수가 있겠죠. 후후...

우리가 지금까지 아무 생각 없이 써 온 $Log:$ 라는 것도 자동 인식표의 하나입니다. 예제에서 보다시피 각 버전에 대한 모든 정보가 소스 파일에 표시가 되게 되죠. 대신 이것은 코멘트(comment)안에 있으므로 컴파일할때 없는 거나 마찬가지겠죠. Id와의 차이점입니다.

5.3 rlog, rcsdiff 명렁어

rlog는 log메시지를 출력하는 것입니다. 그리고 rcsdiff 는 RCS 파일에서 각 버전간의 차이를 diff 유틸리티의 출력 결과와 같은 형태로 출력합니다.

% rlog exam.c

(exam.c의 log 메시지를 출력한다.)

% rcsdiff -r1.2 -r2.0 exam.c

(exam.c에서 1.2 버전과 2.0 버전을 비교한다.)

두 명령어 모두 필요해서 있겠지만 제 생각으로는 별로 쓸 필요는 없는 것 같습니다. 우선 모든 메시지가 소스 파일에 있으니까 rlog가 필요없구요, rcsdiff에 의한 출력 결과는 보통시람이 보기엔 참 어지럽기 때문에 또 필요가 없구... 결론은 ci, co, rcs만 잘 알고 있음 된다는 소리지요.

5.4 GNU make와의 연결

GNU make와 RCS는 찰떡궁합이라고 할만큼 서로 인식을 잘합니다. 즉 make가 Makefile의 내부에서 의존성(dependency - 이것이 몬지 아실런지... Make 강좌에서 자세하게 하죠... 후...)을 조사하다가 파일이 발견되지 않으면 자동적으로 RCS 디렉토리를 뒤져서 co 명령어를 알아서 수행시킨다. 따라서 가장 최신 버전의 파일들이 자동적으로 컴파일되는 이점을 누릴 수가 있다. RCS에서 읽혀진 파일들은 컴파일이 성공하면 자동적으로 삭제가 되므로 디스크 공간도 아낄 수가 있다.

여기서 한가지 더... Makefile 자체도 RCS 파일로 만들어 질 수 있다는 것. 즉, make 명령어를 수행시켰는데 Makefile이 발견되지 않을 때 RCS에서 Makefile,v를 찾아서 자동적으로 Makefile 을 푼다는 것... (상당히 똑똑하지요...)

참고

너무 어지럽지 않으신 지... 강좌를 통해 남을 이해시킨다는 것이 참 힘들다는 것은 절실히 느끼고 있습니다.

다음장 예고

5장이 너무 길어서 다음장으로 연결이 되게 되었습니다. 다음장에서는 RCS를 사용할 때 조심해야 할 여러 가지 사실들에 대해서 말씀드리기로 하죠.


이전페이지 다음페이지 차례