Skip to main content

2 posts tagged with "svn"

View All Tags

· 6 min read

SVN에 있는 merge 기능 중에 이해가 잘 되지 않는 부분이 있어서 몇가지 간단하게 검토해 보았다.

 

환경

나의 경우엔 개발 산출물이 누적되는 trunk가 있고 release만을 위한 branch가 존재하는 상태.

Trunk에서 특정 revision을 release branch에 반영하거나 patch로 사용할 수 있어야 했다.

이런 환경에서 궁금했던 내용은 아래와 같다.

 

1. Two tree merge가 가능한가?

Windows에서 많이 사용되는 TortoiseSVN에는 two tree merge 라는 기능이 존재하는데 command 로는 어떻게 처리해야 할지 알 수가 없었다.

간단하게도 아래와 같은 형태의 command를 실행하면 가능하다.

svn merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]

이미 release branch에서 checkout 한 working copy가 존재하는 상태에서 trunk의 특정 revision을 branch에 반영하고자 했다.

(Working copy 없이 repository 내에서만 처리하고 싶었으나 copy, reintegrate 외에는 그런 기능이 없었기 때문에 부득이하게 working copy를 사용)

위와 같은 형태로 Source1은 branch를 Source2는 trunk를 가리키게 하고 target을 wc로 정하니 문제없이 merge가 가능.

물론 특정 revision을 명시할 수 있어야 했고 이것도 가능.

 

2. 특정 revision을 merge 한다는 것은 해당 revision에 대한 변경사항만 반영하는 것인가?

참조 문서 상으로 @REV의 형태는 1:REV를 의미한다고 한다. 그러므로 @REV 형태로 command를 사용하면 REV에 맞춰서 sync 한다는 의미와 같다.

c (cherry-picking)나 r (revision) 옵션을 사용할 경우 cherry-pick을 한다고 하는데 문서에는 지정하는 revision들의 change-set 만 merge하게 된다고 한다.

그래서 1부터 10까지 한 줄에 하나씩 기록해서 commit 한 revision 10짜리 file을 준비해서,

branch는 trunk의 revision 3을 우선 반영했다. (File은 1, 2, 3이 세 줄에 걸쳐 기록된 상태)

여기서 branch에 trunk의 revision 5를 cherry-pick 하려고 해봤다.

이 때 revision 5의 change-set은 revision 4와 5의 차이가 될 것이라 생각했고 (5가 추가된 상태), merge가 된다면 File에는 1, 2, 3, 5가 기록될거라 예상했다.

하지만 결과는 conflict.

Unified-diff 상으로는 revision 5의 change-set은 4대신 4 + 줄바꿈 + 5 였는데, branch에서 가지고 있는 File은 4가 없기 때문에 merge를 못하는 것이 아닌가 싶다.

Conflict이 발생하는 것으로 봐서는 cherry-pick은 특정 revision 까지가 아니라 (sync가 아니라) revision의 변경사항만 반영하는 것이 맞는 것으로 판단된다.

 

3. 그럼 특정 revision을 patch로 활용하는게 가능한가?

Cherry-pick을 사용하는 이유가 특정 revision에 bug-fix 등이 되어있을 때 그 부분만 가져오기 위해서라고 하는데 한 파일에 대한 revision 차이가 클 경우 conflict이 발생할 가능성이 클 것 같다.

Conflict을 제거하기 위해 --accept theirs-conflict 옵션을 사용해 봤는데 재밌는 결과를 볼 수 있었는데,

위의 과정처럼 branch와 branch의 wc에는 1, 2, 3 까지만 파일에 기록되어 있는 상태에서 trunk의 revision 9 (1부터 9까지 기록된 상태)를 merge 해봤더니

conflict은 물론 없었지만 (발생시 저장소 파일을 선택하게 했으므로) merge 된 파일에는 1부터 9까지 기록되어 있었다.

정리하면 revision 9 까지의 변경이력을 모두 merge 했다는 의미인데 만약 중간의 어떤 revision이 문제점을 갖고 있다면 그 문제까지 merge 될 것이다.

Conflict이 발생하지 않는다면 patch로 활용하는게 가능할 것으로는 생각되는데 conflict 발생시 처리에 대한 것은 여전히 의문으로 남는다.

수작업으로 resolve 한다면 어떻게든 되겠으나 자동화까지 생각했을 때 다른 대안도 마련해야 할 듯.

 

참조

1. SVN merge

2. Advanced Merging

· 3 min read

이런저런 연유로 SVN Server에 직접 접근은 불가능하고 mount를 이용해 file로 접근 가능한 방법을 찾아야만 하는 상황이 생겼다.

그래서 사용하게 된 방법이 SVN mirroring.

미러링에도 여러가지 방법이 있으나 그 중에서 svnsync를 사용하기로 했고 아래처럼 해서 성공.

원격에 있는 SVN 저장소를 $REPO라고 가정하고

로컬에 미러링할 경로를 $MIRROR라고 하자.

1. 우선 빈 저장소를 하나 생성한다.

svnadmin create $MIRROR

2. 오류없이 생성되었다면 $MIRROR/hooks 경로에 pre-revprop-change 라는 파일을 하나 생성한다.

hook에 가보면 임시 파일도 있으니 이용해도 되고 exit 0; 으로 종료되는 파일을 생성해줘도 된다.

pre-revprop-change 라는 파일은 revision 정보가 바뀔 때 실행되는 파일로 보이는데 svnsync 자체를 제한한다거나 하는 용도로 이용 가능.

예를 들어 아래와 같은 내용을 추가해두면 svnsync를 userA 이외에는 사용 못하게 할 수 있다.

(userA가 아닌 경우 실행시 메세지를 출력하고 1을 리턴하면서 실패로 종료됨)

#!/bin/sh USER="$3" if [ "$USER" = "userA" ]; then exit 0; fi echo "Only the userA user can change revprops" >&2 exit 1

3. 그 이후에 실행 권한을 부여한다.

chmod +x $MIRROR/hooks/pre-revprop-change

4. 그 다음은 svnsync 초기화 작업. (원격 SVN 저장소와의 초기화)

svnsync init --username userA file://$MIRROR $REPO

5. 마지막으로 동기화하라고 아래처럼 명령을 내리면 원격 저장소에 있는 내용과 동기화를 하게 된다.

svnsync sync file://$MIRROR

 

문제 중 하나는 sync 명령을 내릴 때만 동기화를 하지 자동으로 동기화를 진행하지는 않는다는건데

post-commit을 이용해 commit 발생시 동기화를 시키도록 스크립트를 만들던지 크론탭 등의 스케줄러를 이용하는 방법을 이용해야 할 것으로 보임.