Rebasing in Mercurial
원문: http://bitquabit.com/post/rebasing-mercurial/
자, 여러분은 git을 선택했습니다. 어쩌면 Mercurial을 선택했을지도 모르죠. 아무튼 지금껏 썼습니다. 문제는 “Merged with stable,” “merged with base” 또는 이와 비슷한 커밋 내용입니다. 이런 커밋은 그다지 쓸모 없는 정보이고 커밋 이력을 완전히 엉망으로 만들어 버립니다. 어떻게 하면 이력을 더 유용하게 할 수 있을까요?
답은 재배치(rebase)에 있습니다. 재배치(rebase)란 아직 다른 저장소로 보내지 않은(not-yet-pushed) 패치를, 마지막으로 패치를 가져온(pull) 저장소의 tip
이 아니라 현재 원격 tip
에 대해 적용하는 git을 통해 널리 알려진 기술입니다. 이것의 이점은 주개발(upstream) 저장소와 병합할 때 단순히 개별적인 병합 하나로 표시하기보다 (주요 브랜치 사이에) 유용한 여러 병합 내용으로 표시합니다.
오늘, 곧 나올 Mercurial 1.1에서 지원할 기능에 대해 동료와 얘기하다 다음 얘기를 듣고 깜짝 놀랐습니다. ”와, 정말 멋져, 드디어 Mercurial에서 재배치를 지원해!” 이번에 나올 Mercurial 버전에서 pull --rebase
명령을 지원하지만 그 이면을 보면 mq
로 처리하는 일 중 일부를 자동화한 것이 전부입니다.
참고: 다음 내용은 최근 Mercurial 버전에서 동작하지만 hg rebase
와, 자매 명령인 hg pull --rebase
를 사용하면 아래에서 설명한 내용을 훨씬 쉽게 처리할 수 있으며, Mercurial에서 MQ를 지원한 것은 현 시점에서 볼 때 1년이 넘었습니다. MQ를 배우기 전에, 사용하는 Mercurial에서 rebase
명령을 지원하는지 hg help rebase
로 확인해 보길 바랍니다. 지원하면 그 명령을 사용하는 게 더 낫습니다.
지금부터 Copilot 개발 저장소를 예로 들어 살펴 보겠습니다.
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 |
gozer:Host benjamin$ hg out comparing with ssh://fcs//hg/copilot-helpers-devel searching for changes changeset: 1937:fe42e5e8e0cf user: Benjamin Pollack <bpollack@fogcreek.com> date: Mon Nov 24 14:49:30 2008 -0500 summary: Make CPUpgrader a proper framework so that OneClick can include it changeset: 1938:20033e199dc7 user: Benjamin Pollack <bpollack@fogcreek.com> date: Mon Nov 24 20:08:06 2008 -0500 summary: Undo accidental rename of Host to OneClick changeset: 1939:127619345a57 tag: tip user: Benjamin Pollack <bpollack@fogcreek.com> date: Mon Nov 24 20:12:39 2008 -0500 summary: Add OneClick gozer:Host benjamin$ hg in stable comparing with ssh://fcs//hg/copilot-helpers-stable searching for changes changeset: 1940:6db7e59a82c5 tag: tip parent: 1936:3140f971d7ab user: Benjamin Pollack <bpollack@fogcreek.com> date: Mon Nov 24 12:38:14 2008 -0500 summary: Added tag 000253 for changeset 3140f971d7ab gozer:Host benjamin$ |
보낼 변경 내용이 세 개이고 가져올 것은 태그만 추가한 것 하나입니다. 명시적으로 병합하면 이력만 아주 복잡하게 만들 뿐 아무런 이점이 없습니다. 완벽한 해결책은 커밋을 재배치하는 겁니다.
이 전투에서 승리할 계획은 다음과 같습니다.
- 보낼 패치를 모두
mq
큐에 추가합니다. - 큐에 추가한 패치를 패치 스택에서 모두 꺼냅니다.
hg pull
로 stable 저장소에서 변경 내용을 가져 옵니다.- 보낼 패치를 다시 적용합니다.
- 패치를 Mercurial 체인지셋으로 다시 변환합니다.
시작해 봅시다. 현재 base 커밋은 체인지셋 fe42e5e8e0cf
이므로 이 체인지셋에서 tip
사이 모든 내용을 mq
에 추가한 후 스택에서 꺼내야 합니다.
1 2 3 4 |
gozer:Host benjamin$ hg qimport -r fe42:tip gozer:Host benjamin$ hg qpop -a Patch queue now empty gozer:Host benjamin$ |
모든 걸 순조롭게 잘 마치면 보낼 패치는 없어야 합니다.
1 2 3 4 5 |
gozer:Host benjamin$ hg out comparing with ssh://fcs//hg/copilot-helpers-devel searching for changes no changes found gozer:Host benjamin$ |
생각한 대로 됐으므로 이제 hg pull -u
로 간단히 원격 저장소에서 변경 내용을 가져올 수 있습니다.
1 2 3 4 5 6 7 8 9 |
gozer:Host benjamin$ hg pull -u stable pulling from ssh://fcs//hg/copilot-helpers-stable searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved gozer:Host benjamin$ |
그런 다음 패치를 다시 적용하고 체인지셋으로 변환합니다.
1 2 3 4 5 6 |
gozer:Host benjamin$ hg qpush -a applying 1937.diff applying 1938.diff applying 1939.diff gozer:Host benjamin$ hg qdelete -r qbase:qtip gozer:Host benjamin$ |
마지막으로, 생각한 대로 됐는지 확인합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
gozer:Host benjamin$ hg glog -l 4 @ changeset: 1940:0b08e0a83965 | tag: tip | user: Benjamin Pollack <bpollack@fogcreek.com> | date: Mon Nov 24 20:12:39 2008 -0500 | summary: Add OneClick | o changeset: 1939:a730a92acb01 | user: Benjamin Pollack <bpollack@fogcreek.com> | date: Mon Nov 24 20:08:06 2008 -0500 | summary: Undo accidental rename of Host to OneClick | o changeset: 1938:01954591e76e | user: Benjamin Pollack <bpollack@fogcreek.com> | date: Mon Nov 24 14:49:30 2008 -0500 | summary: Make CPUpgrader a proper framework so that OneClick can include it | o changeset: 1937:6db7e59a82c5 | user: Benjamin Pollack <bpollack@fogcreek.com> | date: Mon Nov 24 12:38:14 2008 -0500 | summary: Added tag 000253 for changeset 3140f971d7ab | gozer:Host benjamin$ |
완벽합니다. 이력은 한 줄로 나열됐고 변경 내용은 원격 tip
위로 재배치했습니다.
지금까지 한 것은 분명히 hg pull --rebase
보다 더 복잡하지만 Mercurial 1.1을 기다리고 싶지 않다면 지금 당장 같은 기능을 사용할 수 있습니다.
tip
이 아니라 앞으로 가져올 패치의 tip
에 대해 적용한다는 의미입니다.