The Dream of Super Surplus Power

May the force be with you.

overload와 중복 정의

overload

overload@ http://funnyneel.com/funny-image/overload-33

객체 지향 프로그래밍을 조금이라도 학습했다면 overload란 말 역시 알고 있을 겁니다. 다형성과 연관된 것으로 형태가 같은 여러 함수 또는 메소드를 상황에 따라 호출하는 걸 말합니다. 예를 들면 다음과 같습니다.

void foo() { ... }      // 1
void foo(int) { ... }   // 2

int main()
{
    foo();      // 1 호출
    foo(1);     // 2 호출
}

이름이 같은 foo 함수가 둘이지만 컴파일과 실행할 때 오류는 발생하지 않으며 그에 맞는 함수를 호출합니다. 여기서 이를 얘기하려는 것은 아니고 번역 용어에 대해 잠시 얘기해 볼까합니다.

흔히 overload를 중복 정의로 많이 옮깁니다. 또는 오버로드란 말을 그대로 쓰기도 합니다. 중복 정의는 상당히 굳어진 용어이므로 별 거부감 없이 대부분 받아 들입니다. 다만 ODR(one definition rule)에서 얘기하는 중복(duplicate)과 겹친다는 게 문제입니다. 물론 내용상 서로 뜻하는 게 다르지만 의미를 제대로 이해하기 전까지는 헷갈릴 수도 있다고 생각합니다. 그래도 오버로드란 용어를 쓰기도 하고 류광님께서는 중복 적재란 용어를 쓴다고 합니다. 여기서 한 가지 더 생각해 볼 것은 override인데 이는 재정의란 용어로 굳어졌고 그리 문제라 할 것도 없습니다. 다만 overload와 override처럼 번역 용어 역시 함께 맞출 수 있다면 더 좋겠죠.

그래서 생각해 본 게 ‘다중 정의’입니다. 중복 정의가 너무 익숙하다보니 그에 비해 아직 어색하게 느껴지는 면이 있지만 ‘중복’이란 용어 때문에 생기는 오해도 없고 정의를 여러가지로 할 수 있음을 나타내기에 적절하다고 생각합니다. 어느 분께서는 중복이란 단어가 ‘같은 게 또 존재해 낭비가 되다’라는 느낌을 강하게 준다는 의견도 주셨는데 이 말도 동감입니다. 그래서 앞으로는 ‘다중 정의’란 용어를 사용하려 합니다.

Introduction To Mercurial Phases (Part III)

mercurial-logo-droplets-200

원문: http://www.logilab.org/blogentry/88259

이 글은 머큐리얼(Mercurial) 2.1에 구현한 새 기능인 상태(phases)에 대한 일련의 글 중 마지막입니다. 첫 번째 글에서는 상태가 머큐리얼 사용자에게 어떻게 도움이 되는지, 두 번째 글에서는 상태를 어떻게 제어하는지를 설명했습니다. 이 글에서는 업그레이드할 때 주의할 점이 무엇인지 설명합니다.

업그레이드할 때 주의할 점과 하위 호환성

상태를 쓰더라도 저장소를 변환하는 과정은 없습니다. 상태 정보는 체인지셋에 저장하지 않으며 새로운 클라이언트를 쓰는 모든 사용자는 상태의 이점을 얻을 수 있습니다. 하지만 상태가 없는 이전 세계와 상태가 생긴 새로운 세계 사이에 교류에 대해서는 몇 가지 주의해야 할 점이 있습니다.

상태를 사용하는 클라이언트를 사용해 상태를 사용하지 않는 서버와 통신하기

항상 그렇듯이 (http와 ssh를 통해 통신하는) 머큐리얼 통신 프로토콜은 하위 버전과 완전히 호환됩니다. 다만 이전 버전 머큐리얼에서 상태를 인식하지 못하는 것처럼 오래된 서버는 항상 배포 기능이 활성화된 것으로 처리합니다.

상태를 사용하는 클라이언트를 사용해 상태를 사용하지 않는 저장소의 파일 시스템에 직접 접근하기

새 클라이언트에는 이력 중 변경할 수 있는 것과 그렇지 못한 것을 구별할 방법이 없습니다. 안전하게 처리하기 위해 새 저장소에 사용할 수 있는 정보가 없으면 모두 공개(public)로 표시합니다. 첫 번째 글에서 설명한 예에서 만약 머큐리얼 이전 버전으로 복제와 커밋을 하면 새 버전에서는 그 내용을 모두 공개로 인식하고 재배치를 거부합니다.

참고
(mq처럼) 일부 확장 기능에서는 체인지셋을 초안(draft)이나 비공개(secret) 상태로 설정하는 더 영리한 로직을 제공할 수도 있습니다.

상태를 사용하는 클라이언트는 이전 버전으로 사용하던 저장소에 처음 쓰기 동작을 할 때 상태 정보를 기록합니다.

상태를 사용하지 않는 클라이언트를 사용해 상태를 사용하는 저장소의 파일 시스템에 직접 접근하기

이전 버전 클라이언트에서 상태를 보거나 처리할 수 없는 점만 제외하면 모든 것이 잘 동작합니다.

  • 그 저장소에 추가한 체인지셋은 부모의 상태가 무엇이든 해당 부모 상태를 상속합니다. 이 때문에 새 버전 클라이언트로 그 저장소에 접속해 보면 새로 커밋한 것이 공개 상태이거나 pull로 가져온 변경 내용이 초안이나 비공개일 수도 있습니다.
  • 배포 서버로 보낸 체인지셋이 공개로 설정되지 않습니다.
  • 비공개 체인지셋을 교환할 수 있습니다.
  • 이전 버전 클라이언트에서는 변경할 수 없는 체인지셋을 (인식하지 못하므로) 다시 기록할 수도 있습니다.

그러므로 이력을 다시 쓰는 일과 비공개 체인지셋 사용이 매우 많다면 상태가 중요한 그런 저장소는 새 클라이언트로만 사용합니다.

상태 오류 수정하기

다음과 같은 몇몇 상황에서는 저장소에 올바르지 않은 상태가 생길 수 있습니다.

  • 상태를 사용하지 않는 머큐리얼을 사용하는 것으로 업그레이드할 때 선택할 수 있는 기본 상태가 매우 제한적일 수 있습니다.
  • 이전 버전 클라이언트로 저장소를 다루도록 허용할 때
  • 실제 배포하지 않아야 하는 것을 배포 서버로 보낼 때

일관된 상태로 되돌리는 가장 쉬운 방법은 상태 명령을 사용하는 겁니다. 대부분의 경우에 실제 공개 서버에 없는 것을 제외하고 공개 상태인 체인지셋은 초안으로 바꿔야 합니다.

hg phase --force --draft 'public() and outgoing()'

공개 서버가 여럿이라면 pull 명령으로 다른 서버 상태 정보를 가져올 수 있습니다.

결론

머큐리얼 상태는 고급 사용자가 조작하는 것을 막지만 사용자 대부분에게 인식하지 못하는 사이에 안전함을 항상 제공하는 간단한 개념입니다. 이 안전하고 유용한 기능 이면으로 상태는 머큐리얼 코드에 변경할 수 있는 이력을 공유하는 개념을 도입했습니다. 즉 이 기능을 도입함으로써 이력에서 변경 가능한 부분을 안전하고 쉽게 공유하면서 이력을 다시 쓰는 향상된 해결책이 생겼습니다. 조만간 앞으로 추가하게 될 그런 기능에 대해 쓸 겁니다.

머큐리얼 0.9.0 버전과 5년 후에 나올 버전과도 문제 없이 함께 쓸 수 있을 거라고 기대할 수 있습니다.

Introduction To Mercurial Phases (Part II)

mercurial-logo-droplets-200

원문: http://www.logilab.org/blogentry/88219

이 글은 머큐리얼(Mercurial) 2.1에 구현한 새 기능인 상태(phases)에 관한 일련의 글 중 두 번째입니다. 첫 번째 글에서는 상태가 머큐리얼 사용자에게 어떻게 도움이 되는지를 얘기했으며 이 글에서는 어떻게 제어하는지를 설명합니다.

자동으로 이동하는 상태 제어하기

때로는 마무리하지 못한 작업 내용을 공유해야 해서 체인지셋을 초안(draft) 상태로 원격 저장소에 보내거나 그 저장소에서 받아오는 게 적절할 수도 있습니다. 몇 가지 예를 들어 보면 다음과 같은 경우입니다.

  • 지속적인 통합을 위해 원격 저장소로 보낼 때
  • 리뷰를 하기 위해 체인지셋을 원격 저장소 보낼 때
  • 사용자가 여러 머신에서 작업할 때
  • 브랜치를 복제할 때

저장소 설정 파일에서 배포 동작을 비활성화할 수 있습니다.

[phases]
publish=False

저장소를 배포할 수 없게 설정하면 상태 변경 없이 체인지셋을 다른 저장소로 보낼 수 있습니다. 초안인 체인지셋은 초안으로, 공개인 체인지셋은 공개 상태를 그대로 유지한 채 다른 저장소로 들어갑니다.

celeste@Chessy ~/palace $ hg showconfig phases
phases.publish=False
babar@Chessy ~/palace $ hg log --graph
@  [draft] add a carpet (2afbcfd2af83)
|
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…
babar@Chessy ~/palace $ hg outgoing ~celeste/palace/
[public] Add wall color (0d1feb1bca54)
[public] Add a table in the kichen (139ead8a540f)
[draft] add a carpet (3c1b19d5d3f5)
babar@Chessy ~/palace $ hg push ~celeste/palace/
pushing to ~celeste/palace/
searching for changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 2 files
babar@Chessy ~/palace $ hg log --graph
@  [draft] add a carpet (2afbcfd2af83)
|
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…
celeste@Chessy ~/palace $ hg log --graph
o  [draft] add a carpet (2afbcfd2af83)
|
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…

그리고 그 원격 저장소에서 가져오면 그 저장소에 있는 상태를 그대로 유지합니다.

celeste@Chessy ~/palace $ hg up 139ead8a540f
celeste@Chessy ~/palace $ echo The wall will be decorated with portraits >> bedroom
celeste@Chessy ~/palace $ hg ci -m 'Decorate the wall.'
created new head
celeste@Chessy ~/palace $ hg log --graph
@  [draft] Decorate the wall. (3389164e92a1)
|
| o  [draft] add a carpet (3c1b19d5d3f5)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…
---
babar@Chessy ~/palace $ hg pull ~celeste/palace/
pulling from ~celeste/palace/
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
babar@Chessy ~/palace $ hg log --graph
@  [draft] Decorate the wall. (3389164e92a1)
|
| o  [draft] add a carpet (3c1b19d5d3f5)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…

상태 정보는 pullpush 동작을 할 때 교환합니다. 어떤 체인지셋이 양쪽 저장소에 모두 있으면서 상태가 다르다면 가장 낮은 상태로 통일합니다. 예를 들어 어떤 체인지셋이 지역 저장소에서는 초안이지만 원격 저장소에서는 공개라면 공개로 설정합니다.

celeste@Chessy ~/palace $ hg push -r 3389164e92a1
pushing to http://hg.celesteville.com/palace
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
celeste@Chessy ~/palace $ hg log --graph
@  [public] Decorate the wall. (3389164e92a1)
|
| o  [draft] add a carpet (3c1b19d5d3f5)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…
---
babar@Chessy ~/palace $ hg pull ~celeste/palace/
pulling from ~celeste/palace/
searching for changes
no changes found
babar@Chessy ~/palace $ hg log --graph
@  [public] Decorate the wall. (3389164e92a1)
|
| o  [draft] add a carpet (3c1b19d5d3f5)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…

참고: pull은 읽기 전용 동작이며 원격 저장소에 있는 상태를 바꾸지 않습니다.

새로 커밋하는 체인지셋의 상태를 제어할 수도 있습니다. 새 체인지셋 중 명시적으로 승인한 것만 다른 저장소로 보내려면 설정을 다음처럼 바꿉니다.

[phases]
new-commit=secret

이제 체인지셋을 다른 저장소로 보내려면 상태 이동을 직접 처리해야 합니다. 자세한 내용은 다음 절에서 설명합니다.

참고: 지금까지 다룬 내용과 함께 ‘새 커밋을 비공개로 만드는 가장 실용적인 방법’은 다음처럼 하는 겁니다.

hg commit --config phases.new-commit=secret

상태 이동 직접 처리하기

상태 이동은 대부분 인식하지 못하는 사이에 자동으로 처리됩니다. 하지만 여전히 hg phase 명령으로 직접 상태 이동을 처리할 수도 있습니다.

babar@Chessy ~/palace $ hg log --graph
@    [draft] merge with Celeste works (f728ef4eba9f)
|\
o |  [draft] add a carpet (3c1b19d5d3f5)
| |
| o  [public] Decorate the wall. (3389164e92a1)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
…
babar@Chessy ~/palace $ hg phase --public 3c1b19d5d3f5
babar@Chessy ~/palace $ hg log --graph
@    [draft] merge with Celeste works (f728ef4eba9f)
|\
o |  [public] add a carpet (3c1b19d5d3f5)
| |
| o  [public] Decorate the wall. (3389164e92a1)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
…

체인지셋은 일반적인 동작을 하는 동안 더 낮은 상태로만 이동합니다. 기본적으로 상태 명령은 이 규칙을 따릅니다.

babar@Chessy ~/palace $ hg phase --draft 3c1b19d5d3f5
no phases changed
babar@Chessy ~/palace $ hg log --graph
@    [draft] merge with Celeste works (f728ef4eba9f)
|\
o |  [public] add a carpet (3c1b19d5d3f5)
| |
| o  [public] Decorate the wall. (3389164e92a1)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
…

하지만 --force 스위치를 사용해 이런 동작을 무시할 수도 있습니다.

경고: 상태는 사용자가 hg phase --force 를 사용하지 않아도 되도록 설계했습니다. 만약 --force를 사용해야 하는 일반적인 이유가 있다면 뭔가 잘못하고 있는 겁니다. 자신의 요구에 적합하게 상태 이동이 자동으로 처리되도록 설정하는 방법을 보려면 이전 절 내용을 읽어 보세요.

babar@Chessy ~/palace $ hg phase --verbose --force --draft 3c1b19d5d3f5
phase change for 1 changesets
babar@Chessy ~/palace $ hg log --graph
@    [draft] merge with Celeste works (f728ef4eba9f)
|\
o |  [draft] add a carpet (3c1b19d5d3f5)
| |
| o  [public] Decorate the wall. (3389164e92a1)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
…

이력 그래프에서 상태가 일관된 리비전 집합을 정의하고 있는 점에 주목합니다. 즉 (변경할 수 없는) 공개 체인지셋의 조상은 모두 변경 불가 상태여야 한다는 것을 뜻합니다. 또한 (교환할 수 없는) 비공개 체인지셋의 후손은 모두 비공개가 됩니다. 이는 체인지셋의 상태를 바꾸는 것은 결국 다른 체인지셋의 상태를 바꿀 수도 있다는 것을 뜻합니다.

babar@Chessy ~/palace $ hg phase -v --public f728ef4eba9f # merge with Celeste works
phase change for 2 changesets
babar@Chessy ~/palace $ hg log --graph
@    [public] merge with Celeste works (f728ef4eba9f)
|\
o |  [public] add a carpet (3c1b19d5d3f5)
| |
| o  [public] Decorate the wall. (3389164e92a1)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
…
babar@Chessy ~/palace $ hg phase -vf --draft 3c1b19d5d3f5 # add a carpet
phase change for 2 changesets
babar@Chessy ~/palace $ hg log --graph
@    [draft] merge with Celeste works (f728ef4eba9f)
|\
o |  [draft] add a carpet (3c1b19d5d3f5)
| |
| o  [public] Decorate the wall. (3389164e92a1)
|/
o  [public] Add a table in the kichen (139ead8a540f)
|
…

다음이자 마지막 글에서는 이전 버전 머큐리얼과 상태를 지원하는 새 버전을 함께 쓰는 법에 대해 설명합니다.

자신의 hgrc 파일에서 설정해도 됩니다.
상태 순서는 공개 < 초안 < 비공개 입니다.

Introduction To Mercurial Phases (Part I)

mercurial-logo-droplets-200

원문: http://www.logilab.org/blogentry/88203

Logilab을 대표해 Mercurial 2.1에 상태(phases)라는 새 핵심 기능을 넣으려고 많은 노력을 기울였습니다. 상태는 체인지셋을 공유했는지 또는 공유해야 하는지 추적하는 시스템입니다. (예를 들어 확장 기능인 mq나 rebase로) 이력을 변경할 때 흔히 하는 실수를 막는데 도움이 되므로 분명히 모든 사용자에게 이익입니다. 여기서 설명하는 개념은 머큐리얼(Mercurial)에서 이력을 간단하면서도 안전하게 다시 쓰는 강력한 기법에 대한 첫 걸음입니다.

이  시리즈는 모두 3회로 나눠 게재하며 다음 내용을 설명합니다.

  1. 상태가 머큐리얼 사용자에게 어떻게 도움이 되는지
  2. 상태를 제어하는 방법
  3. 이전 버전 머큐리얼과 상태를 지원하는 새 버전을 함께 쓰는 방법

이력을 다시 쓸 때 많이 하는 실수 막기

DVCS에서 이력을 다시 쓰는 건 일반적입니다. 하지만 잘못된 방법으로 했을 때 얻는 결과인 중복 이력(duplicated history)은 가장 흔한 오류입니다. 상태는 이력을 더 안전하게 다시 쓰기 위한 개념입니다. 이를 위해 머큐리얼 2.1에서는 이력에서 (영원히 변하지 않을 것으로 기대하는) ‘과거’ 부분과 (현재 변경하고 있는) ‘현재’ 부분을 구별합니다. 즉 이력에서 오래되고 바뀌지 않는 부분을 공개(public), 바뀌는 부분을 초안(draft)이라고 합니다.

간단한 예를 통해 살펴 보겠습니다.


새 머큐리얼 사용자가 저장소를 복제합니다.

babar@Chessy ~ $ hg clone http://hg.celesteville.com/palace
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 2 files
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
babar@Chessy ~/palace $ cd palace
babar@Chessy ~/palace $ hg log --graph
@  changeset:   1:2afbcfd2af83
|  tag:         tip
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:41:56 2012 +0100
|  summary:     We need a kitchen too.
|
o  changeset:   0:898889b143fb
   user:        Celeste the Queen <Celeste@celesteville.com>
   date:        Wed Jan 25 16:39:07 2012 +0100
   summary:     First description of the throne room

저장소에는 이미 체인지셋이 몇 개 있으며 사용자는 내용을 고친 후 커밋합니다.

babar@Chessy ~/palace $ echo The wall shall be Blue >> throne-room
babar@Chessy ~/palace $ hg ci -m 'Add wall color'
babar@Chessy ~/palace $ echo In the middle stands a three meters round table >> kitchen
babar@Chessy ~/palace $ hg ci -m 'Add a table in the kichen'

하지만 새 체인지셋을 원격 저장소로 보내려 할 때 다른 개발자가 먼저 그 저장소로 보낸 것이 있다는 것을 알게 됩니다.

babar@Chessy ~/palace $ hg push
pushing to http://hg.celesteville.com/palace
searching for changes
abort: push creates new remote head bcd4d53319ec!
(you should pull and merge or use push -f to force)
babar@Chessy ~/palace $ hg pull
pulling from http://hg.celesteville.com/palace
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
babar@Chessy ~/palace $ hg log --graph
o  changeset:   4:0a5b3d7e4e5f
|  tag:         tip
|  parent:      1:2afbcfd2af83
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:58:23 2012 +0100
|  summary:     Some bedroom description.
|
| @  changeset:   3:bcd4d53319ec
| |  user:        Babar the King <babar@celesteville.com>
| |  date:        Wed Jan 25 16:52:02 2012 +0100
| |  summary:     Add a table in the kichen
| |
| o  changeset:   2:f9f14815935d
|/   user:        Babar the King <babar@celesteville.com>
|    date:        Wed Jan 25 16:51:51 2012 +0100
|    summary:     Add wall color
|
o  changeset:   1:2afbcfd2af83
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:41:56 2012 +0100
|  summary:     We need a kitchen too.
|
o  changeset:   0:898889b143fb
   user:        Celeste the Queen <Celeste@celesteville.com>
   date:        Wed Jan 25 16:39:07 2012 +0100
   summary:     First description of the throne room

참고: 지금부터는 있음직하지 않은 상황입니다. 머큐리얼에 익숙치 않은 사용자라도 이런 사소한 상황에 혼란스러워 하지 않을 정도로 머큐리얼은 매우 간단합니다. 하지만 상태에 초점을 맞추기 위해 예를 단순하게 합니다.

최근에 이 머큐리얼 초보자는 ‘재배치(rebase)’와 한 줄로 나열한 이력(linear history)의 이점에 대한 멋진 글을 읽었으므로 이력을 병합하지 않고 다시 쓰기로 맘 먹습니다. 재배치에 대한 멋진 도움말을 읽기도 했지만 이 초보자는 막상 사용할 때는 실수를 합니다. 즉 원격 체인지셋인 0a5b3d7e4e5f:”Some bedroom description.” 을 자신이 변경한 체인지셋 위에 재배치하기로 한 거죠. 이전 버전 머큐리얼에서는 이런 실수를 허용했기에 체인지셋 0a5b3d7e4e5f:”Some bedroom description.”이 중복으로 생기는 문제가 있었습니다.

babar@Chessy ~/palace $ hg rebase -s 4 -d 3
babar@Chessy ~/palace $ hg push
pushing to http://hg.celesteville.com/palace
searching for changes
abort: push creates new remote head bcd4d53319ec!
(you should pull and merge or use push -f to force)
babar@Chessy ~/palace $ hg pull
pulling from http://hg.celesteville.com/palace
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
babar@Chessy ~/palace $ hg log --graph
@  changeset:   5:55d9bae1e1cb
|  tag:         tip
|  parent:      3:bcd4d53319ec
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:58:23 2012 +0100
|  summary:     Some bedroom description.
|
| o  changeset:   4:0a5b3d7e4e5f
| |  parent:      1:2afbcfd2af83
| |  user:        Celeste the Queen <Celeste@celesteville.com>
| |  date:        Wed Jan 25 16:58:23 2012 +0100
| |  summary:     Some bedroom description.
| |
o |  changeset:   3:bcd4d53319ec
| |  user:        Babar the King <babar@celesteville.com>
| |  date:        Wed Jan 25 16:52:02 2012 +0100
| |  summary:     Add a table in the kichen
| |
o |  changeset:   2:f9f14815935d
|/   user:        Babar the King <babar@celesteville.com>
|    date:        Wed Jan 25 16:51:51 2012 +0100
|    summary:     Add wall color
|
o  changeset:   1:2afbcfd2af83
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:41:56 2012 +0100
|  summary:     We need a kitchen too.
|
o  changeset:   0:898889b143fb
   user:        Celeste the Queen <Celeste@celesteville.com>
   date:        Wed Jan 25 16:39:07 2012 +0100
   summary:     First description of the throne room

복잡한 조직에서 이는 매우 흔한 실수이며 심지어 크고 성공적인 프로젝트이거나 다른 DVCS를 쓰더라도 마찬가지입니다. 머큐리얼 새 버전에서는 사용자가 더 이상 이런 실수를 할 수 없습니다. 잘못된 방법으로 재배치를 하려 할 때 결과는 다음과 같습니다.

babar@Chessy ~/palace $ hg rebase -s 4 -d 3
abort: can't rebase immutable changeset 0a5b3d7e4e5f
(see hg help phases for details)

올바른 방법으로 재배치를 하면 잘 동작합니다.

babar@Chessy ~/palace $ hg rebase -s 2 -d 4
babar@Chessy ~/palace $ hg log --graph
@  changeset:   4:139ead8a540f
|  tag:         tip
|  user:        Babar the King <babar@celesteville.com>
|  date:        Wed Jan 25 16:52:02 2012 +0100
|  summary:     Add a table in the kichen
|
o  changeset:   3:0d1feb1bca54
|  user:        Babar the King <babar@celesteville.com>
|  date:        Wed Jan 25 16:51:51 2012 +0100
|  summary:     Add wall color
|
o  changeset:   2:0a5b3d7e4e5f
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:58:23 2012 +0100
|  summary:     Some bedroom description.
|
o  changeset:   1:2afbcfd2af83
|  user:        Celeste the Queen <Celeste@celesteville.com>
|  date:        Wed Jan 25 16:41:56 2012 +0100
|  summary:     We need a kitchen too.
|
o  changeset:   0:898889b143fb
   user:        Celeste the Queen <Celeste@celesteville.com>
   date:        Wed Jan 25 16:39:07 2012 +0100
   summary:     First description of the throne room

위 내용을 설명하면 다음과 같습니다.

  • Celeste가 변경한 체인지셋 0a5b3d7e4e5f은 원격 저장소에서 가져온 것이므로 공개(public) 상태로 설정됐습니다. 공개 상태는 변경할 수 없습니다.
  • (0d1feb1bca54, 139ead8a540f로 재배치한) 체인지셋 f9f14815935d와 bcd4d53319ec는 커밋 후 다른 저장소로 보내지 않았으므로 초안(draft) 상태입니다. 공개 상태와 달리 초안 상태는 변경할 수 있습니다.

전체 내용을 하나씩 자세히 살펴 보겠습니다. 상태에 주목하세요.

babar@Chessy ~ $ cat >> ~/.hgrc << EOF
[ui]
username=Babar the King <babar@celesteville.com>
logtemplate='[{phase}] {desc} ({node|short})\\n'
EOF

첫째, 공개 서버에서 복제한 체인지셋은 공개입니다.

babar@Chessy ~ $ hg clone --quiet http://hg.celesteville.com/palace
babar@Chessy ~/palace $ cd palace
babar@Chessy ~/palace $ hg log --graph
@  [public] We need a kitchen too. (2afbcfd2af83)
|
o  [public] First description of the throne room (898889b143fb)

둘째, 새로 커밋한 체인지셋은 초안 상태입니다.

babar@Chessy ~/palace $ echo The wall shall be Blue >> throne-room
babar@Chessy ~/palace $ hg ci -m 'Add wall color'
babar@Chessy ~/palace $ echo In the middle stand a three meters round table >> kitchen
babar@Chessy ~/palace $ hg ci -m 'Add a table in the kichen'
babar@Chessy ~/palace $ hg log --graph
@  [draft] Add a table in the kichen (bcd4d53319ec)
|
o  [draft] Add wall color (f9f14815935d)
|
o  [public] We need a kitchen too. (2afbcfd2af83)
|
o  [public] First description of the throne room (898889b143fb)

셋째, 공개 서버에서 가져온 체인지셋은 공개입니다.

babar@Chessy ~/palace $ hg pull --quiet
babar@Chessy ~/palace $ hg log --graph
o  [public] Some bedroom description. (0a5b3d7e4e5f)
|
| @  [draft] Add a table in the kichen (bcd4d53319ec)
| |
| o  [draft] Add wall color (f9f14815935d)
|/
o  [public] We need a kitchen too. (2afbcfd2af83)
|
o  [public] First description of the throne room (898889b143fb)

참고: 재배치를 해도 상태는 그대로 유지합니다.

babar@Chessy ~/palace $ hg rebase -s 2 -d 4
babar@Chessy ~/palace $ hg log --graph
@  [draft] Add a table in the kichen (139ead8a540f)
|
o  [draft] Add wall color (0d1feb1bca54)
|
o  [public] Some bedroom description. (0a5b3d7e4e5f)
|
o  [public] We need a kitchen too. (2afbcfd2af83)
|
o  [public] First description of the throne room (898889b143fb)

마지막으로, 일단 공개 서버로 보내고 나면 체인지셋은 (변경할 수 없는) 공개 상태가 됩니다.

babar@Chessy ~/palace $ hg push
pushing to http://hg.celesteville.com/palace
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 2 files
babar@Chessy ~/palace $ hg log --graph

@  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
o  [public] Some bedroom description. (0a5b3d7e4e5f)
|
o  [public] We need a kitchen too. (2afbcfd2af83)
|
o  [public] First description of the throne room (898889b143fb)

요약하면 다음과 같습니다.

  • 다른 저장소와 교환한 체인지셋은 공개 상태이며 변경할 수 없습니다.
  • 커밋한 체인지셋은 다른 저장소로 보내기 전까지 초안 상태입니다.
  • 사용자 입장에서는 상태를 걱정할 필요가 없습니다. 상태는 인식하지 못하는 사이에 자연스럽게 이동합니다.

완전하지 않은 이력을 교환하지 못하도록 하기

공개 상태에서는 사용자가 의도하지 않게 공개 이력을 다시 쓰는 경우를 막아 줍니다. 이것으로도 좋지만 상태를 사용하면 한 발짝 더 나아갈 수 있습니다. 상태를 사용하면 처음부터 의도치 않게 이력을 공개하는 것을 막을 수 있습니다. 이를 위한 세 번째 상태가 있는데 바로 비공개(secret) 상태입니다. 이 비공개 상태와 멋지게 통합되어 있는 mq 확장 기능을 사용해 설명하겠습니다.

mq 확장 기능을 활성화합니다.

babar@Chessy ~/palace $ vim ~/.hgrc
babar@Chessy ~/palace $ cat ~/.hgrc
[ui]
username=Babar the King <babar@celesteville.com>
[extensions]
# enable the mq extension included with Mercurial
hgext.mq=
[mq]
# Enable secret phase integration.
# This integration is off by default for backward compatibility.
secret=true

(일반적인 커밋이 아니라) 새 패치를 비공개로 만듭니다.

babar@Chessy ~/palace $ echo A red carpet on the floor. >> throne-room
babar@Chessy ~/palace $ hg qnew -m 'add a carpet' carpet.diff
babar@Chessy ~/palace $ hg log --graph

@  [secret] add a carpet (3c1b19d5d3f5)
|
@  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…

이 비공개 체인지셋은 outgoingpush 명령을 사용할 때 포함하지 않습니다.

babar@Chessy ~/palace $ hg outgoing
comparing with http://hg.celesteville.com/palace
searching for changes
no changes found (ignored 1 secret changesets)
babar@Chessy ~/palace $ hg push
pushing to http://hg.celesteville.com/palace
searching for changes
no changes found (ignored 1 secret changesets)

게다가 다른 사용자가 볼 수도 없습니다.

celeste@Chessy ~/palace $ hg incoming ~babar/palace/
comparing with ~babar/palace
searching for changes
[public] Add wall color (0d1feb1bca54)
[public] Add a table in the kichen (139ead8a540f)

상태 이동은 mq 확장 기능에서 처리하며 qfinish를 하면 체인지셋은 초안 상태가 됩니다.

babar@Chessy ~/palace $ hg qfinish .
babar@Chessy ~/palace $ hg log --graph
@  [draft] add a carpet (2afbcfd2af83)
|
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…

그리고 qimport를 하면 체인지셋은 다시 비공개가 됩니다.

babar@Chessy ~/palace $ hg qimport -r 2afbcfd2af83
babar@Chessy ~/palace $ hg log --graph
@  [secret] add a carpet (2afbcfd2af83)
|
o  [public] Add a table in the kichen (139ead8a540f)
|
o  [public] Add wall color (0d1feb1bca54)
|
…

당연히 공개 체인지셋에 qimport를 사용할 수 없습니다.

babar@Chessy ~/palace $ hg qimport -r 139ead8a540f
abort: revision 4 is not mutable

다음 글에서는 상태 이동을 제어하는 방법에 대해 자세히 설명합니다.

Pages:12345