일단 CVS를 쓰던 당시 어떻게 했냐 하면... 아주 간단했다.
usemodkr
디렉토리 - 공개용 버전을 개발하는 디렉토리
wiki
디렉토리 - 이 GyparkWiki에 사용되는 디렉토리. 설정파일, 스타일쉬트, 매크로, wiki.pl 등이 수정됨
보통 다음과 같은 순서로 소스수정 작업을 함
usemodkr
디렉토리에서 작업한다.
CVS Repo
로 commit
wiki
디렉토리로 이동
wiki
쪽에서 update를 수행할 때, 대부분의 경우는 usemodkr
에서 고친 부분이 고스란히 wiki
에 있는 소스에도 반영이 되지만, 간혹 wiki
쪽에서 독자적으로 고친 부분과 충돌이 일어날 때가 있다.
이렇게 충돌이 발생하면, 아무리 짧은 시간이라 해도 서버 에러가 나는 등 영향을 받는 것이 제일 불만이었다.
wiki
로 바로 update하지 않고, wiki
와 동일한 상태로 수정이 되어 있는 디렉토리(wiki_test
라고 하자)를 하나 더 만들어서 거기에서 먼저 update하여 테스트한 후 이상이 없으면 그 때 wiki
에서 update하는 방법을 고려한 적이 있었는데 (오래전 일이라 잘 기억나지 않지만) 이 경우 다음 세 가지가 문제였다:
wiki
와 wiki_test
에 동일하게 적용해야 하는데 이걸 CVS로 어떻게 해야 할 지 몰라서 수작업으로 하려니 힘들었다.
wiki_test
와 wiki
두 곳에 있는 소스가 완전히 동일하면 좋겠지만, 홈페이지주소간단히하기를 적용하자니 wiki
에 있는 소스는 반드시 "wiki"라는 이름의 디렉토리에 있을 때만 제대로 동작했다. 따라서 wiki_test
는 저 주소간단히하기 패치를 적용하지 않은 상태로 두어야 하므로 이 두 디렉토리의 소스가 또 서로 달라져야 했다.
wiki_test
에서 update를 해서 충돌이 발생한다는 걸 알았다 해도, wiki
에서도 충돌이 발생할 것이라는 걸 미리 알 수 있을 뿐, wiki
에서 update할 때는 충돌이 발생하지 않고 곧바로 merge가 될 수 있게 하는 방법을 알 수 없었다. 기껏해야 수작업으로 충돌을 해결한 파일을 미리 만들어두었다가 wiki
에서 update한 후 재빨리 덮어쓰는 정도였는데, 두번째 이유 때문에 wiki_test
와 wiki
사이의 소스도 좀 달라야 했기 때문에 미리 wiki
에 덮어쓸 파일을 만드는 것도 은근히 손이 많이 가는 일이었음
CVS에도 브랜치란 개념이 있었으니 이걸 잘 쓰면 어떻게 일관성있게 통합할 수 있었을 것 같긴 한데, 굳이 그것까지 공부하고 싶지 않았었음.
이게 아주 오묘한데... 솔직히 말하면 Git 말고 Mercurial이 초반 습득 난이도가 낮고 명령어가 덜 많다는 얘기를 듣고는 그걸 익힐 걸 그랬나 하고 후회하는 중이다 -_-;; 뭐 막상 hg를 썼다면 Git가 기능이 정말 많다던데 그걸 쓸 걸 그랬나 하고 후회하고 있을지도. 암튼 내가 Git를 제대로 이해하고 있는지 자신이 없지만.
어쨌거나, 몇 개의 저장소를 유지할 지를 먼저 고민해봤는데,
wiki
하나만 사용하면서 공개용과 gyparkwiki용 브랜치를 각각 운영
usemodkr
에서 공개버전 작업, wiki
에서 gyparkwiki 버전 작업
usemodkr
에서 공개버전 작업. wiki_test
에서는 usemodkr의 변경을 pull한 후 gyparkwiki 버전 작업 및 테스트. wiki
에서 wiki_test의 변경을 pull하여 반영
usemodkr
에서 공개버전, gyparkwiki 테스트, 최종 gyparkwiki 버전 전부를 브랜치로 나누어 작업하고, 최종 결과를 wiki
에서 pull해서 바로 적용
아래는 설 연휴 전후로 구상하고 PC에서 간단한 저장소를 만들어 테스트하면서 좌충우돌을 거쳐 나온 것들.
일단 이런 형태로 UseModKr
디렉토리를 저장소로 꾸몄다.
---A---B---C master \ S mywiki
master
브랜치: [github 저장소]에 push하고, UseModWiki소스수정/Download에 tarball로 업로드하는, 공개용 소스
mywiki
브랜치: 이곳 GyparkWiki 에 쓰기 위해 설정파일, 스타일쉬트, 매크로 등을 수정(이 수정은 S
에 해당)한 소스. 이것을 wiki
디렉토리에 push를 하거나 그쪽에서 pull을 해서 갱신
첫번째 희망
앞으로 소스를 수정해 나가더라도, 항상 위와 같이
공개용 master 브랜치 + 내 홈페이지용 수정 = mywiki 브랜치
형태를 유지했으면 좋겠다고 생각했음
희망: ---A---B---C---D---E---F UseModKr/master \ S' UseModKr/mywiki
wiki 디렉토리 쪽에서 merge하면 이렇게 보인다: ---A---B---C---S---D---E---F---S' wiki/mywiki ^ ^
차선책(물론, 희망사항)
새로 작업할 때마다 추가되는 커밋들을 rebase해서, 두 브랜치가 서로 병행해서 자라는 형태도 떠올려 보았음
피하고 싶었음: ---A---B---C---D---E---F master \ S---D'--E'--F' mywiki
별 수 없이
애초에 위와 같은 구성을 희망했던 이유가, Git의 merge란 게... CVS를 쓸 때처럼 단지 소스가 병합되는 것이 아니라, 서로 별개의 브랜치 상에 있는 커밋을 다시 한 곳에서 이어서 진행하는 형태로 구성되더라. (사실 내가 CVS를 제대로 알고 쓰던 게 아니라서 확신은 없다) 그래서 history를 보면 자꾸 갈라졌다 합쳐지는게, 내겐 아직 적응하기가 힘들다. 최대한 rebase 기능을 써서, 변경내역이 하나의 선으로 나타나게 하고 싶었던 것.
O
가 merge를 나타내는 커밋)
정말 피하고 싶었음: ---A---B---C---D---E---F master \ \ S-----------O mywiki
추가로 필요한 브랜치들
여기에 추가로, 신경써야 할 게 더 있었다.
추가하려는 기능이 특정 Perl 모듈이 필요한 경우가 있다. 나는 서버에 root권한이 없어서 내 홈 계정에 모듈을 설치해야 하는데, 이 경우 위키 소스에는 @INC
배열에 내 홈 계정 경로를 추가해서 모듈을 찾을 수 있게 해야 한다. 그러나 공개할 소스에는 그 부분이 들어 있으면 안 된다. 이렇게, 작업하는 동안에는 테스트를 위해서 수정되었다가, 최종 공개 시점에는 원상복구시켜놔야 하는 부분이 있다. 그래서 그 부분을 별도의 브랜치로 뽑았다.
I devel_base / ---A---B---C master \ S mywiki
게다가 앞에서도 적었지만, mywiki 브랜치 쪽에도 문제가 있는게... 홈페이지주소간단히하기를 적용해 놨더니만, 작업하던 디렉토리에서 mywiki 브랜치를 체크아웃한 후 테스트를 해 보려 했더니, 링크들이 죄다 wiki/ 디렉토리로 걸리는 바람에 링크만 클릭했다 하면 작업 디렉토리를 벗어나버린다. 따라서 주소간단히하기 적용을 일단 취소해놔야 한다. 즉 mywiki를 테스트하려 해도 선행작업이 필요하고, 테스트가 끝난 후 실제로 내 홈페이지에 적용하기 직전에 그 선행작업 부분을 다시 되돌려야 한다는 얘기.
I devel_base / ---A---B---C master \ S mywiki \ W mywiki_test
테스트는 I와 W커밋에서 시작해야 하는데, 최종 결과는 그 두 커밋은 빠져야 하고 C와 S의 라인에서 바로 이어져야 한다...는게 상황을 아주 귀찮게 만들고 있다.
그럼 전에 CVS로는 이런 문제가 없었냐 하면... 그 때는 아예 방법을 몰라서 매번 손으로 I와 W에 해당하는 작업을 해주고, 테스트가 끝난 후 다시 찾아서 지워줬다 -_-;;; 그래서 사실, 버전업된 위키소스 tar.gz 파일을 공개한 후에야 그걸 지우지 않았다는 걸 깨닫고 부랴부랴 다시 고치고 압축해서 공개하고 한 적도 많음.
그럼 실제로 소스수정할 때 어떤 식으로 할 지 순서를 적어보자. 이 문서를 작성하는 시점에서는 계속 간단한 저장소를 가지고 테스트만 해 봤고 실제로 위키소스를 수정하며 적용해보지는 못 했다.
1. UseModKr
저장소 - CVS에서 갓 넘어온 상태
I devel_base (공개버전 테스트에 필요한 로컬 수정) / ---A---B---C master (공개될 버전) \ S mywiki (내 홈페이지 버전) \ W mywiki_test (내 홈페이지 테스트에 필요한 로컬 수정)
2. 새로운 기능을 추가 하기 위해서 devel_base에서 topic 브랜치 분기. 그냥 devel_base에서 고쳐도 되겠지만, 브랜치를 분기하면 하다가 아니다 싶으면 브랜치를 없애면 되니까 더 나을 듯.
$ git co -b topic devel_base [ 작업하고 커밋하고 반복 ]
T1--T2 topic / I devel_base / ---A---B---C master \ S mywiki \ W mywiki_test
3. 잘 된다 싶으면 master에 일단 합치자.
I
가 끼어들어버리니까 곤란. 여기는 정말 rebase해야 함
$ git rebase --onto master devel_base topic
T1--T2 topic / | I devel_base |/ ---A---B---C master \ S mywiki \ W mywiki_test
4. devel_base의 경우는 외부에 push되는 일 없는 브랜치니까, 맘대로 rebase 가능. 다음 번에 새로운 기능을 추가할 때 간편하게 할 수 있도록, 지금 끝으로 빼두자.
(devel_base)$ git rebase topic
I devel_base / T1--T2 topic / ---A---B---C master \ S mywiki \ W mywiki_test
5. 이제 master는 topic과 합친다.
(master)$ git merge topic1
I devel_base / ---A---B---C--T1--T2 master, topic \ S mywiki \ W mywiki_test
6. 이제 gyparkwiki에 적용할 버전을 만들자. 이 디렉토리에서 테스트를 하려면 W
위에서 해야 하므로, merge한다.
$ git co mywiki_test (mywiki_test)$ git merge master
I devel_base / ---A---B---C--T1--T2 master, topic \ \ S \ mywiki \ \ W-------O mywiki_test
7. 별 문제가 없으면, 이제 S
에 master를 merge한다.
$ git co mywiki (mywiki)$ git merge topic1
I devel_base / ---A---B---C--T1--T2 master, topic \ |\ S-----O \ mywiki \ \ W-------O mywiki_test
wiki
디렉토리에서만 완전히 제대로 동작한다. (홈페이지주소간단히하기 적용 때문에) 따라서 mywiki_test와 달리 mywiki 브랜치는 이 상태에서 테스트를 하는 게 불편하다. 페이지 링크를 클릭하는 순간 현재 디렉토리를 빠져나가 wiki디렉토리 쪽으로 넘어가버리니 주의해야 함
8. topic 브랜치는 이제 필요 없으니 지워도 되고, 기록을 위해 남기고 싶으면 남겨도 될 듯 (그러나 그런 용도라면 tag를 쓰는 게 나으려나)
$ git branch -d topic
9. 이제 wiki
디렉토리 쪽에서는 여기 있는 mywiki 브랜치를 가져간다.
$ cd ../wiki (mywiki)$ git pull
10. 이후에 또 새로운 기능을 추가한다면 UseModKr
저장소의 모습은 아마도 다음과 같을 것이다.
I devel_base / ---A---B---C--T1--T2--T3--T4 master, new_topic \ |\ |\ S-----O-\-----O \ mywiki \ \ \ W-------O-------O mywiki_test
10-1. 생각해보니 mywiki는 rebase를 하면 곤란하니 merge를 한다 치고, mywiki_test는 매번 저렇게 merge할 게 아니라, mywiki까지 작업이 끝난 후에 W 커밋만 뒤로 옮겨 붙여도 될 듯?
I devel_base / ---A---B---C--T1--T2--T3--T4 master, new_topic \ | | S-----O-------O mywiki \ W' mywiki_test
(mywiki_base) $ git reset --hard W # 일단 W지점까지 롤백하고 (mywiki_base) $ git rebase mywiki # mywiki 뒤로 붙임
음, Git에서는 디렉토리를 묘사하는 오브젝트의 명칭이 tree라서, 여기서도 트리라고 말하면 혼동의 여지가 있겠지만, 달리 좋은 표현이 떠오르지 않네.
암튼, 현재 저장소에 있는 모든 브랜치의 내역을 전부 보고 싶으면
git log --pretty=oneline --all --graph --decorate
등으로 할 수는 있겠지만 아무래도 GUI 툴도 쓰게 된다.
그런데 msysgit에 같이 있는 gitk를
gitk --all
와 같이 실행하면... 어떻게든 브랜치들의 진행 라인을 왼쪽 컬럼부터 채워서 적으려고 하는지 자꾸 갈라졌던 브랜치들의 라인이 틈만 나면 왼쪽으로 다시 합쳐지려고 한다.
말로 설명하기 복잡하니 그림으로: 현재 위키소스수정을 하면서 매번 새로운 토픽 브랜치를 만들어 작업하고, 끝나면 master 브랜치에 합치는 식으로 하려고 노력하고 있다. 그러면 하다가 아니다 싶으면 브랜치를 바로 날려버리면 되니까. 그래서 브랜치가 9개일 때의 상황인데, gitk의 출력을 도저히 내가 알아보기 힘들어서 다시 엑셀에 정리를 좀 해 보았다. 엑셀에서는 한 컬럼이 하나의 브랜치고 아래에서 위쪽으로 진행이 되고 있고, 빨간 선은 브랜치가 새로 분기하는 거고 파란 점선은 merge이다.
암튼 gitk의 출력은 너무 알아보기 힘들어서, 다른 게 없나 싶어서 gitk 매뉴얼 페이지 마지막에 있는 다른 툴을 알아봤는데,
엑셀로 매번 정리하는 것도 화딱지 나는 일이라서 -_-; Perl 스크립트(GitFancygraph)를 만들어 git의 출력을 가지고 재배열하게 해보았다.
브랜치들 간의 커밋들의 진행관계를 나타내주는 [git-todo 플러그인]도 참고.
흐음, 2.16a 버전 작업하면서 처음으로 mywiki와 master를 merge하는데 충돌 발생. 이건 아마도, mywiki를 처음에 내가 구성할 때 rebase를 한 번 하는 바람에 ISBNLink 함수를 수정한 커밋이 양쪽에서 두 번 들어가 있는 상태여서, 그걸 다시 수정한 2.16a의 커밋과 충돌한 것 같다. 그 다음 2.17 ditaa 플러그인 작업할 때는 아무 문제 없었는데, 이거야 새로운 파일 하나만 추가된 것이니 당연하고... 차후에 wiki.pl을 고치는 다른 작업을 할 때 확인해봐야겠음.