본문 바로가기

Programming

시나리오 별 SVN 사용법

원본 : http://imcdream.net/221


[SVN 사용 준비]
svn import : Repository에 version이 붙이 않은 사본을 올리는 것.
필요하다면 intermeidate directory를 만든다. Working Copy가 없어도 바로 commit 된다.
이미 존재하는 file/tree를 subversion repository에 tracking을 시작할 때 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
$ svnadmin create /var/svn/newrepos
$ svn import mytree file:///var/svn/newrepos/some/project \
             -m "Initial import"
Adding         mytree/foo.c
Adding         mytree/bar.c
Adding         mytree/subdir
Adding         mytree/subdir/quux.h
Committed revision 1.
$ svn list file:///var/svn/newrepos/some/project
bar.c
foo.c
subdir/

import가 완료되었다고 해서 원래 tree가 Working Copy로 바뀌는 것은 아니다.
Working Copy로 바꿔주기 위해서는 checkout을 해야 한다.

Repository 추천 layout : 개발의 줄기를 갖는 trunk directory, 가지 사본을 갖는 branches directory,tag copy를 갖는 tags directory의 구조를 추천한다.
1
2
3
4
$ svn list file:///var/svn/repos
/trunk
/branches
/tags

최초의 Checkout : Working Copy를 생성하기 위해 최초의 Checkout을 실행한다.
이 Copy는 Subversion repository의 HEAD(최종 revision)을 갖는다.
1
$ svn checkout http://svn.collab.net/repos/svn/trunk

특정 directory를 골라서 checkout 할 수 있다.
1
$ svn checkout http://svn.collab.net/repos/svn/trunk/subversion/tests/cmdline/

Working copy에 생성되는 .svn directory는 subversion에의해 관리되는 중요한 directory이므로 삭제하거나 수정하지 않도록 주의한다.
local의 특정 directory에 Working Copy를 생성할 수 있다.
1
2
3
$  svn checkout http://svn.collab.net/repos/svn/trunk subv
A    subv/Makefile.in
A    subv/ac-helpers

[Basic Work Cycle]

1) Update Working Copy (svn update) : Working Copy를 최신 revision으로 update.

2) Make changes (svn add, svn delete, svn copy, svn move, svn mkdir) : local에서 이미 Working Copy에 존재하는 file을 수정하는 것은 상관이 없으나, 새로운 file을 생성하거나, 기존의 file을 삭제하거나, file을 이동시키거나, 새로운 directory를 만들거나 기존의 directory를 삭제하면 Subversion에 "mark"를 요청해야 한다.
mark가 되더라도, Commit 하기 전에는 Repository에 반영되지 않는다.

- svn add file or directory : file이나 directory를 추가한다.
directory를 추가하면, directory에 포함된 모든 file이나 directory도 함께 추가된다.

- svn delete file or directory : file이나 directory, symbolic link등을 Repository에서 제거한다.
file이나 link라면 Working Copy에서 즉시 제거되지만, directory라면 Subversion schedule에서만 제거된다.
Commit하게 되면, Working copy와 Repository 모두에서 제거된다.

- svn copy src dst : src에서 dst를 복사한다. directory를 생성하지는 않는다.

- svn move src dst : copy와 같지만, src는 삭제한다. 역시 directory를 생성하지는 않는다.

- svn mkdir directory : local에서 directory를 만들고 svn add 하는 것과 같다.

3) Examine changes (svn status, svn diff) : 위의 변화를 만든 뒤 Repository에 반영하기 위해 Commit을 하기 전 다시 한 번 점검할 수 있도록 도와준다.
svn status는 대략적인 변화를, svn diff는 자세한 내용을 확인할 수 있게 한다.

svn status는 다음과 같은 code로 정보를 제공한다.
?       scratch.c           # version control되지 않는 file
A       stuff/loot/bloo.h   # 추가 예정된 file
C       stuff/loot/lump.c   # update시 conflict가 생긴 file
D       stuff/fish.c        # 삭제 예정된 file
M       bar.c               # local에서 내용이 바뀐 file

--verbose(-v) option을 주면, Revision, 최종 수정되었던 Revision, 최종 수정한 사람의 id를 함께 확인 할 수 있다.
1
2
3
4
5
6
7
8
9
10
$ svn status -v
M               44        23    sally     README
                44        30    sally     INSTALL
M               44        20    harry     bar.c
                44        18    ira       stuff
                44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
                44        21    sally     stuff/things
A                0         ?     ?        stuff/things/bloo.h
                44        36    harry     stuff/things/gloo.c

--show-update(-u) option을 주면, 날짜가 지난(out-of-date) file을 * 표시로 확인 할 수 있다.
1
2
3
4
5
6
7
$ svn status -u -v
M      *        44        23    sally     README
M               44        20    harry     bar.c
       *        44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
A                0         ?     ?        stuff/things/bloo.h
Status against revision:   46

svn diff를 사용하면 보다 자세한 정보를 확인 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ svn diff
Index: bar.c
===================================================================
--- bar.c    (revision 3)
+++ bar.c    (working copy)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>

 int main(void) {
-  printf("Sixty-four slices of American Cheese...\n");
+  printf("Sixty-five slices of American Cheese...\n");
 return 0;
 }

Index: README
===================================================================
--- README    (revision 3)
+++ README    (working copy)
@@ -193,3 +193,4 @@
+Note to self:  pick up laundry.

Index: stuff/fish.c
===================================================================
--- stuff/fish.c    (revision 1)
+++ stuff/fish.c    (working copy)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.

Index: stuff/things/bloo.h
===================================================================
--- stuff/things/bloo.h    (revision 8)
+++ stuff/things/bloo.h    (working copy)
+Here is a new file to describe
+things about bloo.

unified diff format으로 출력되며, patch program을 만들 때에도 유용하다.
1
$ svn diff > patchfile

4) Possibly undo some changes (svn revert) : svn diff에서 잘못 수정했다는 걸 발견했다면, 이전으로 되돌릴 수 있다(undoing).
1
2
$ svn revert README
Reverted 'README'

svn revert는 add나 delete등 모든 operation을 취소 할 수 있다.

5) Resolve conflicts (merge other's changes - svn update, svn resolve) : svn update를 하면 conflict 여부를 확인 할 수 있다.
1
2
3
4
5
6
$ svn update
U  INSTALL
G  README
Conflict discovered in 'bar.c'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (h) help for more options:

code U는 local에서 변화가 없었으나 Repository에서 갱신이 일어난 경우다.
code G는 merGed를 의미하며 local과 Repository 양쪽에서 변화가 있었으나 중첩되지 않은 경우이다.
bar.c에서 발견된 conflict는 interactive conflict resolution으로, local의 변화와 Repository의 변화가 중첩되었다는 뜻이다.

이를 해결하기 위해 몇가지 command를 제공하는데, 그 command는 다음과 같다.

- (p)ostpone : conflicted state로 내버려 둔다. update가 완료되면, 알아서 고쳐야 한다.
postpone으로 넘어가면, svn status에서 C(conflict) code로 표시되며, unversion된 3개의 file을 Working Copy에 생성한다.
filename.mine(Update하기 전에 수정했던 Working Copy의 file), filename.rOLDREV(Working Copy에서 수정하기 위해 사용했던 Base Revision), filename.rNEWREV(Repository에서 가져온 HEAD Revision).

예를 들면, 다음과 같이 생성된다.
1
2
3
4
5
6
7
8
9
10
11
$ svn update
Conflict discovered in 'sandwich.txt'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (h)elp for more options : p
C  sandwich.txt
Updated to revision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2

이 상황에서, 새로 생긴 3개의 file이 삭제되기 전에는 sandwich.txt가 commit되지 않는다.

conflict를 해결한 후 3개의 파일을 없애기 위해서는 svn resolve accept 명령을 사용한다.
1
2
$ svn resolve --accept working sandwich.txt
Resolved conflicted state of 'sandwich.txt'

local에서 작업한 내용을 버리고 Repository에서 받은 걸 사용하여 conflict를 해결할 때도 역시 resolve accept 명령을 사용한다.
1
2
3
4
5
6
7
8
9
10
$ svn update
Conflict discovered in 'sandwich.txt'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (h) help for more options: p
C    sandwich.txt
Updated to revision 2.
$ ls sandwich.*
sandwich.txt  sandwich.txt.mine  sandwich.txt.r2  sandwich.txt.r1
$ svn resolve --accept theirs-full sandwich.txt
Resolved conflicted state of 'sandwich.txt'

local에서 작업한 내용을 되돌려(Working Copy Base Revision으로) 다시 작업을 하려면 svn revert 명령을 사용한다.
1
2
3
4
$ svn revert sandwich.txt
Reverted 'sandwich.txt'
$ ls sandwich.*
sandwich.txt

- (d)iff : unified diff format으로 conflict가 발견된 file과 base revision(Working Copy의 이전 내용)을 비교하여 보여준다.
1
2
3
4
5
6
7
8
9
10
11
Select: (p) postpone, (df) diff-full, (e) edit,
        (h)elp for more options : d
--- .svn/text-base/sandwich.txt.svn-base      Tue Dec 11 21:33:57 2007
+++ .svn/tmp/tempfile.32.tmp     Tue Dec 11 21:34:33 2007
@@ -1 +1,5 @@
-Just buy a sandwich.
+<<<<<<< .mine
+Go pick up a cheesesteak.
+=======
+Bring me a taco!
+>>>>>>> .r32

- (e)dit : 환경 변수로 설정해둔 editor를 사용하여 conflict file을 수정한다.

- (r)esolved : file을 수정한 뒤, svn에게 해결되었다고 알린다.

- (m)ine-(f)ull : Repository에서 받은 걸 무시하고 local에 있는 것을 사용한다.

- (t)heirs-(f)ull : local에 있는 걸 무시하고 Repository에서 받은 것을 사용한다.

- (l)aunch : 외부 program을 사용하여 conflict를 해결한다.

- (h)elp : 도움말 출력.

6) Commit changes (svn commit) : update가 끝나면, Repository에 commit한다.
1
2
$ svn commit -m "Corrected number of cheese slices."
$ svn commit -F logmsg

-m(--message) option을 사용하여 log message를 직접 작성할 수도 있고, -F(--file) option을 사용하여 특정 file에서 log message를 읽어낼 수도 있다.

commit할 때 다른 사람이 수정하여 HEAD Revision이 변경되면 commit이 실패한다.
1
2
3
4
$ svn commit -m "Add another rule"
Sending        rules.txt
svn: Commit failed (details follow):
svn: File '/sandwich.txt' is out of date

이럴 때에는, svn update를 다시 하여 commit 할 수 있도록 한다.

[Examining History]

Subversion에서 변화된 내용을 살펴 볼 수 있다.

1) svn log : commit할 때 작성했던 message를 살펴 본다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ svn log
------------------------------------------------------------------------
r3 | sally | 2008-05-15 23:09:28 -0500 (Thu, 15 May 2008) | 1 line

Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | 2008-05-14 18:43:15 -0500 (Wed, 14 May 2008) | 1 line

Added main() methods.
------------------------------------------------------------------------
r1 | sally | 2008-05-10 19:50:31 -0500 (Sat, 10 May 2008) | 1 line

Initial import
------------------------------------------------------------------------

Revision, Commit한 사람, 날짜, 시간, message를 볼 수 있다.

revision(-r) option을 사용하면 특정 범위의 Revision에 해당하는 내용을 볼 수 있다.
1
2
3
$ svn log -r 5:19    # shows logs 5 through 19 in chronological order
$ svn log -r 19:5    # shows logs 5 through 19 in reverse order
$ svn log -r 8       # shows log for revision 8

특정 파일에 대한 내용만 볼 수도 있다.
1
2
$ svn log foo.c
$ svn log http://foo.com/svn/trunk/code/foo.c

수정된 파일들의 경로를 포함한 목록을 보고 싶으면 --verbose(-v) option을 사용한다.
1
2
3
4
5
6
7
8
9
$ svn log -r 8 -v
------------------------------------------------------------------------
r8 | sally | 2008-05-21 13:19:25 -0500 (Wed, 21 May 2008) | 1 line
Changed paths:
   M /trunk/code/foo.c
   M /trunk/code/bar.h
   A /trunk/code/doc/README
Frozzled the sub-space winch.
------------------------------------------------------------------------

2)svn diff : 파일에서 구체적으로  수정된 내용을 비교하여 살펴 볼 수 있다.
local에서 수정한 파일과 수정한 원본(Working Copy Revision)을 비교한다.
1
2
3
4
5
6
7
8
9
10
11
12
$ svn diff
Index: rules.txt
===================================================================
--- rules.txt    (revision 3)
+++ rules.txt    (working copy)
@@ -1,4 +1,5 @@
 Be kind to others
 Freedom = Responsibility
 Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking

--revision(-r) option을 사용하여 Working Copy와 Repository를 비교한다.
1
2
3
4
5
6
7
8
9
10
11
12
$ svn diff -r 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt    (revision 3)
+++ rules.txt    (working copy)
@@ -1,4 +1,5 @@
 Be kind to others
 Freedom = Responsibility
 Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking

Repository Revision에서 특정한 Revision들의 file을 비교한다.
1
2
3
4
5
6
7
8
9
10
11
$ svn diff -r 2:3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt    (revision 2)
+++ rules.txt    (revision 3)
@@ -1,4 +1,4 @@
 Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
 Everything in moderation
 Chew with your mouth open

--change(-c) option으로 Repository에서 지정한 Revision과 그 이전 Revision의 file을 비교할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
$ svn diff -c 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt    (revision 2)
+++ rules.txt    (revision 3)
@@ -1,4 +1,4 @@
 Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
 Everything in moderation
 Chew with your mouth open
$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt

3) svn cat : Repository에서 지정한 Revision의 특정 file을 열어보거나 복사한다.
1
2
3
4
$ svn cat -r 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
$ svn cat -r 2 rules.txt > rules.txt.v2

4) svn list : Repository에 있는 file과 directory를 확인한다.
1
2
3
4
5
6
$ svn list http://svn.collab.net/repos/svn
README
branches/
$ svn list -v http://svn.collab.net/repos/svn
  20620 harry            1084 Jul 13  2006 README
  23339 harry                 Feb 04 01:40 branches/

!! option을 아무 것도 주지 않으면, 현재 Working Directory에 해당하는 Repository의 directory를 보여준다. (local이 아님!)

5) 특정 Revision을 지정한 작업
svn checkout이나 svn update에 --revision(-r) option을 사용하여 해당 Revision의 file들을 받아 올 수 있다.
1
2
$ svn checkout -r 1729 # Checks out a new working copy at r1729
$ svn update -r 1729 # Updates an existing working copy to r1729

Release를 위해 .svn directory가 포함되지 않은 local copy를 만들 수 있다.
1
2
$ svn export http://svn.example.com/svn/repos1 # Exports latest revision
$ svn export http://svn.example.com/svn/repos1 -r 1729 # Exports revision r1729

[Cleanup]

svn server와 작업도중 interrupt가 들어와 lock이 걸린 채로 작업이 중단 되었을 때 lock을 풀어주기 위한 명령.
1
2
3
4
5
6
$ svn status
  L    somedir
M      somedir/foo.c
$ svn cleanup
$ svn status
M      somedir/foo.c

lock이 걸리면 L이 표시된다.