목공책 하나 들이셔요~

2013년 12월 20일 금요일

[Hg] 3. Mercurial 실수를 되돌리는 법

이 글은 Joel Spolsky가 저술한 Mercurial 튜토리얼 시리즈 중에서 네번째 글인 "Fixing Goofs"를 번역한 것입니다. 원문은 다음 링크를 참조하세요. http://hginit.com/03.html

Mercurial은 당신에게 자유롭게 여러가지 시도를 할 수 있게 해 줍니다. 통상적인 편집 과정에서 어떤 실수로 인해 대재앙을 맞았다고 가정해보죠. 아래 처럼요.


emacs를 사랑해야겠습니다. (위와 같이 글자를 바꾼 것은 Pig Latin이라는 규칙에 의한 것입니다. emacs에는 Pig Latin 모드가 지원되어서 위와 같이 전체 문장을 한꺼번에 Pig Latin식으로 바꿀 수 있습니다)

어쨌든 모든 걸 잃은건 아닙니다. 이 치명적인 실수로부터 되돌아가는 가장 보편적인 방법은 hg revert 커맨드를 쓰는 것입니다.


위 커맨드는 가장 최근의 커밋시의 상태로 파일을 되돌려 줄 겁니다. Mercurial은 삭제하는 걸 좋아하지 않습니다. 그래서 잘못 변환된 파일을 지우기 보다는 이름을 바꾸어 저장합니다.


위와 같이 hg revert를 하게 되면 원래 편집하던 파일은 .orig 확장자를 붙여 이름이 바뀝니다. 그러므로 다시 Pig Latin 변형된 레서피를 살리려면 guac.orig 파일을 guac로 바꾸면 됩니다. 그리고 한단게 더 나아가 커밋까지 해버린다면? 어떻게 복구해야 할까요?


"Pig Latin 짱~" 이라는 코멘트가 붙은 이 마지막 커밋은 hg rollback 커맨드로 무효화 시킬 수 있습니다. 단 이 커밋이 중앙 서버나 다른 레포지토리로 push되지 않은 상태여야 합니다. 그리고 마지막 하나의 커밋만 무효화 시킬 수 있습니다.


또 다른 상황을 한번 상상해 봅시다. 당신 회사의 사장이 Jim이라는 새로운 디자이너를 고용했는데 그가 한 일주일간의 작업물이 너무 맘에 들지 않습니다. 그래서 싹 없애버리고 당신걸로 바꾸고 싶은데 이 Jim이 좀 성깔이 더러워서 함부로 바꿨다가는 골치가 아플 판이니다. 그래서 당신은 당신이 새롭게 디자인한 결과물을 만들어 놓고 다른 사람들의 지지를 받을 계획입니다.

Mercurial에서는 레포지토리의 어떤 실험적인 클론(clone)을 만들 수 있습니다.


비효율적으로 보이지만 사실 그렇지 않습니다. recipes와 recipes-experiment 작업 영역은 동일한 히스토리를 공유합니다. Mercurial은 하드 링크(hard link)라는 파일시스템이 지원하는 트릭을 이용하기 때문에 실제 작업영역의 복제는 매우 빠르고 디스크 사용량도 적습니다.

이제 이 실험적인 브랜치에서 무지막지한 변경을 할 수 있습니다.


이게 바로 저의 위대한 실험적인 구아카몰 레서피입니다.


이 실험적인 레포지토리에서 당신은 마음껏 커밋을 할 수 있습니다.


당신은 마음껏 변경하고 작업할 수 있습니다. 커밋도 원할때 아무때나 할 수 있습니다. 그것이 설사 미친것 같은 실험이라 할지라도 당신은 이 레포지토리에 대해 전권을 가지고 있습니다. 그리고 다른 사람에게 영향을 주지도 않습니다.

만일 이 실험이 잘못된 걸로 판명된다면 그냥 이 실험적인 디렉토리 전체를 삭제하면 됩니다. 그럼 됩니다.

하지만 이 실험이 잘 동작한다면 이 변경사항을 중앙 레포지토리로 push해야 합니다.


음 근데 이 변경사항들이 어디 레포지토리로 등록된 걸까요? hg path를 이용하면 알 수 있습니다.


"default"로 지정된 곳이 바로 hg push 커맨드를 내리면 레포지토리가 push될 곳을 의미합니다. 보통 다른 레포지토리를 지정하지 않으면 애초에 레포지토리를 클론(clone)한 곳이 저장될 곳입니다. 이 경우는 로컬 디렉토리로 표시되었지만 원격인 경우 URL이 표시됩니다.


잊지 마세요. 좀 전에 recipes-experimental 레포지토리로부터 recipes로 push했다는 걸요. 그래서 recipes 레포지토리에서의 log를 보면 조금 전 push한 내용을 볼 수 있습니다.


하지만 이게 작업할 파일까지 바뀌게 한 건 아닙니다. hg parent로 보면 체인지셋 #4를 사용하고 있음을 볼 수 있습니다.


보셨듯이 "Queso"관련 내용은 체인지셋 #5에 있습니다. 하지만 제 메인 레포지토리는 아직 체인지셋 #4에 머물고 있습니다. 다시 말해 누군가 제 레포지토리로 변경 내용을 push하더라도 제 작업 영역이 바로 변경되지는 않음을 기억하십시요.


만일 체인지셋 #5의 내용을 받고 싶다면 hg update 커맨드를 내리면 됩니다.


무슨 일이 일어났는지 아시겠나요? 변경 내용이 제 레포지토리로 날아오면 그 것들은 제가 작업하고 있는 버전 위에 올라앉게 됩니다. push와 pull은 단지 다른 레포지토리로 변경 내용들을 보낼 뿐입니다. 이들은 실제 작업하고 있는 파일에 영향을 주지는 않습니다.

지금 현재의 상태를 그림으로 그려보면 이렇습니다.


Mercurial은 변경 내용을 다른 레포지토리로 보내는 것에 대해 매우 유연합니다. 당신은 실험적인 레포지토리에서 바로 중앙 레포지토리로 push할 수도 있습니다.


위의 push는 실험적인 레포지토리의 체인지셋 #5를 바로 중앙 레포지토리로 보내는 겁니다. 이제 제 로컬 레포지토리로 돌아와 보면 이제 더 이상 push할 것이 없음을 볼 수 있습니다.


중앙 레포지토리는 이 변경 내용들이 어디로부터 온 것인지 알기 때문에 Mercurial은 깔끔하게 이런 복잡한 레포지토리의 변경 관계를 해결할 수 있습니다.

어떤 경우는 몇달 전에 저질렀던 실수가 발견되기도 합니다.


포테이토 칩이라구요? 젠장맞을~

Mercurial은 오래된 체인지셋을 철회(backout)할 수 있는 기능을 제공합니다. 철회는 변경된 내용을 반대로 되돌려서 원래 파일과 결합하여 새로운 문서를 만들어냅니다. 또띠야 칩을 지우고 포테이토 칩을 넣었던 리비젼 2를 철회해 보도록 합시다.


이럴수가~ 무슨 일이 생긴거죠?


오래된 변경 내용을 역으로 Undo하여 현재 버전과 병합할 수 있는 것이 바로 hg backout의 기능입니다.

아주 오래된 변경 내용의 경우 종종 어떤 혼란스러움에 의해서 자동으로 병합되지 않는 경우가 있습니다. 이럴 때는 수작업으로 충돌을 해결해 주어야 하는데... 이에 대해서는 다음 글에서 살펴 보겠습니다.

스스로 해보세요

이 튜토리얼을 읽고 스스로 해보세요.

1. 체크인 하기 전에 혹은 체크인 한 후에 실수로 변경한 내용들을 원래대로 복구하세요.
2. 실험적인 변경을 위해 레포지토리를 로컬에 복제(clone)하세요.
3. 다른 레포지토리로 push해 보세요.
4. 아주 오래된 실수들을 복구해 보세요.

댓글 없음:

댓글 쓰기