Hg : git의 rebase와 같은 rebase를 수행하는 방법


207

힘내에서 나는 이것을 할 수있다 :

1. 새로운 기능에 대한 작업을 시작하십시오.
$ git co -b newfeature-123 # (로컬 기능 개발 지점)
몇 가지 커밋을 수행하십시오 (M, N, O)

마스터 A --- B --- C
                \
새로운 기능 -123 M --- N --- O

2. 업스트림 마스터에서 새로운 변경 사항을 가져옵니다.
git pull
(ff 커밋으로 업데이트 된 마스터)

마스터 A --- B --- C --- D --- E --- F
                \
새로운 기능 -123 M --- N --- O

3. 새로운 기능을 갖도록 마스터를 리베이스 해제 
최신 업스트림 변경에 대비하여 개발할 수 있습니다.
(newfeature-123에서)
$ git rebase 마스터

마스터 A --- B --- C --- D --- E --- F
                            \
새로운 기능 -123 M --- N --- O


Mercurial에서 동일한 작업을 수행하는 방법을 알고 싶습니다. 웹에서 답변을 찾아 보았지만 찾을 수있는 최선은 다음과 같습니다. git rebase-hg do it

그 링크는 2 가지 예를 제공합니다 :
1. 나는 이것을 인정할 것입니다 :

hg -CF  
hg 지점 -f newfeature-123  
HG 이식 -a -b newfeature-123 

pre-rebase MNO를 병합되지 않은 헤드로 남겨두고 업데이트 된 메인 라인에서 분기되는 것을 나타내는 3 개의 새로운 커밋 M ', N', O '을 생성한다는 점을 제외하고는 나쁘지 않습니다.

기본적으로 문제는 내가 이것으로 끝내는 것입니다.

마스터 A --- B --- C --- D --- E --- F
                \ \
newfeature-123 \ M '--- N'--- O '
                  \
새로운 기능 -123 M --- N --- O

삭제해야 할 로컬의 원치 않는 커밋을 남겨두기 때문에 좋지 않습니다.

  1. 동일한 링크의 다른 옵션은
hg qimport -r M : O
hg qpop -a
H를 위로
hg 지점 newfeature-123
hg qpush -a
hg qdel -r qbase : qtip

그리고 이것은 원하는 그래프를 만듭니다 :

마스터 A --- B --- C --- D --- E --- F
                            \
새로운 기능 -123 M --- N --- O

그러나이 명령들 (모두 6 개)은 훨씬 더 복잡해 보입니다.

$ git rebase 마스터

이것이 Hg에서 유일하게 동등한 지 또는 Git과 같은 간단한 다른 방법이 있는지 알고 싶습니다.


7
"삭제해야 할 로컬의 원치 않는 커밋을 남기므로 좋지 않습니다." -실제로 git도 같은 일을합니다. 원래 브랜치에서 커밋을 변경하거나 제거하지 않고 마스터 위에 동일한 변경 사항을 적용하는 새로운 커밋을 만듭니다. 당신은 여전히 ​​오래된 것들에 액세스 할 수 있으며 git reflog가비지 수집을 할 때까지 완전히 사라지지 않습니다. 당신이 reflog를 사용할 필요가 없도록 지명 된 브랜치에 그것들을 유지하려면 git branch feature-123_originalrebasing하기 전에 수행하십시오 .
MatrixFrog

5
임의의 질문 : 변경 세트 / 분기를 ASCII로 그렸습니까? 아니면 그렇게하는 도구가 있습니까?
Amir Rachum

2
TextWrangler를 "덮어 쓰기"로 설정 한 상태에서 직접 수행했습니다.
jpswain

답변:


235

VonC는 여러분이 찾고있는 답변 인 Rebase Extension을 가지고 있습니다. 그러나 왜 수은에서 mq 나 rebase가 기본적으로 활성화되지 않는지에 대해 두 번째 또는 두 번째 생각을하는 것은 가치가 있습니다. 거의 매일 묘사하는 방식으로 일할 때 내가 취하는 패턴은 다음과 같습니다.

1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream mainline:
$ hg pull

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. merge master into my clone so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F

master A---B---C---D---E---F
                \           \
newfeature-123   M---N---O---P

그리고 그것이 정말로 필요한 전부입니다. 나는 새로운 기능-123 클론으로 끝납니다. 내가 행복 할 때 쉽게 메인 라인으로 되돌릴 수 있습니다. 그러나 가장 중요한 것은 역사를 바꾸지 않았습니다 . 누군가 내 cset을보고 원래 코딩 된 내용과 작업 내내 메인 라인의 변화에 ​​어떻게 반응했는지 확인할 수 있습니다. 모든 사람이 그 가치를 가지고 있다고 생각하는 것은 아니지만, 우리가 원하는 바가 아니라 실제로 일어난 일을 보여주는 것이 소스 제어의 일이라고 확고한 신자입니다. 다른 역사 편집 기술은 그것을 숨 깁니다.

이제 soapbox를 치우는 동안 VonC의 답변을 선택하십시오. :)


18
참고 : 물론 Git은 정확하게 기록을 다시 쓸 수 없으며 새로운 것을 쉽게 만들 수 있습니다 ( utcc.utoronto.ca/~cks/space/blog/tech/GitNewHistory ). RebaseExtension을 추가함으로써 Mercurial은 기존 기록을 새로운 기록으로 대체하는 동일한 방법을 제공합니다. 왜? 병합이 항상 정답이되는 것은 아니기 때문에, 특히 변경 세트가 F가 아닌 F의 진화 로보아야 할 때 (P는 O의 위에 병합 됨)
VonC

19
VonC는 합병이 항상 올바른 선택은 아니라고 생각하지만 그 차이점은 VCS 역사가 그들에게 말할 수 있기를 원한다는 것입니다. 역사는 항상 "처음에는 통합하지 않았지만 당시에는 쓸모가 없다고 생각했던 방식"과 같은 질문에 대답 할 수 있어야한다고 생각합니다 . 과학자들은 페이지 번호가 매겨진 로그 북을 펜에 보관하고 AFAIC 소프트웨어 엔지니어는 입력 한 모든 바이트를 저장해야합니다. 기록을 다시 작성하고 심지어 cset 부모도 가능하지만 확실히 CollapseExtension, HistEdit 등이이를 위반합니다. 그것은 전적으로 개인적인 선택의 문제입니다.
Ry4an Brase

14
개인 선택 +1 Git을 사용하면 결과적으로 사소한 분기에 rebase를 사용하고 사소하지 않은 경우에 병합합니다. 이를 통해 필자가 중요하다고 생각하는 병합 기록을 보존 할 수 있지만 대부분 로그를 깨끗하고 선형으로 유지합니다.
Kos

16
또한 나는 많은 작은 커밋을 먼저 수행 한 다음 조인하고 레이블을 지정하고 정리 한 다음 메인 브랜치와 다시 병합 (또는 리베이스)하는 경향이 있기 때문에 많은 대화 형 리베이스를 수행합니다. 코딩 및 관리 변경 사항을 별도의 단계로 수행하는 것이 좋습니다.
Kos

6
"개발 경로를 따라 모든 바이트를 저장"한다는 철학은 기여자가 패치 세트를 제안한 다음 관리자의 피드백을 기반으로 재 작업하는 대규모 오픈 소스 프로젝트에는 적합하지 않습니다. 그런 다음 기본 프로젝트 저장소에는 모든 변경 사항의 올바른 버전이 있으며 모든 관련 변경 사항이 단일 커밋에 있습니다. git interactive rebase는 작업 변경 사항을 트리를 손상시키지 않는 일련의 커밋으로 정리하고 커밋 메시지를 사용하여 모든 작업을 마친 후에 말하기로 결정한 것을 반영합니다.
Peter Cordes

104

Rebase Extension을 찾고있을 것 입니다. ( SummerOfCode 2008의 일부로 구현 됨 )

이러한 경우 로컬 변경 사항을 "분리"하고 리포지토리를 주류와 동기화 한 다음 새 변경 사항 위에 개인 변경 사항을 추가하는 것이 유용 할 수 있습니다. 이 작업을 리베이스라고합니다.

오시는 길 :

대체 텍스트

에:

대체 텍스트


마찬가지로 아래 주석 에 의해 steprobe :

변경 사항을 가져 오지 않고 리포지토리에 두 개의 분기가있는 경우 (을 사용하여keepbranches ) 할 수 있습니다 .

hg up newfeature-123 
hg rebase -d master --keepbranches

( --keepbranches: 원래 지점 이름을 상속합니다.)

모카 언급 :

나는을 사용하는 것을 좋아 hg rebase --source {L1's-sha} --dest {R2's-sha}하지만 --keepbranches끝에 추가 할 수 있는지 몰랐습니다 .

으로 아래 그림 에서 조나단 블랙번 :

 hg rebase -d default --keepbranches

1
Rebase Extension을 살펴 보았지만 여전히 명확하지 않습니다. 위에서 설명한 것을 수행하는 단계를 설명해 주시겠습니까?
jpswain

6
당신의 변화를 당겨되지 않으며, 당신은 당신의 repo에있는 두 개의 지점을 가지고있는 경우에, 당신은 할 수 있습니다 : hg up newfeature-123다음hg rebase -d master --keepbranches
steprobe

2
나는 rebase에 아무런 문제가 없다고 생각합니다. 그것은 단지 선택의 문제입니다. 문제는 rebase가 남용되고 @ Ry4an과 함께있어 기록을 다시 쓰지 않으므로 발생하는 상황과시기를 알 수 있습니다.
Jorge Vargas

@steprobe : --keepbranches 사용에 대한 힌트를 주셔서 감사합니다. 나는을 사용하는 것을 좋아 hg rebase --source {L1's-sha} --dest {R2's-sha}하지만 --keepbranches끝에 추가 할 수 있는지 몰랐습니다 . 이것은 다른 낮은 순위의 답변에 언급되어 있지만이 답변에 명시 적으로 쓰면 좋을 것입니다.
Mojca

@Mojca 문제 없습니다. 그에 따라 답변을 편집했습니다.
VonC

44

현대적인 Hg 설치가 있다고 가정하면 간단하게 추가 할 수 있습니다.

[extensions]
rebase = 

~ / .hgrc로

그런 다음 명령을 사용할 수 있습니다 hg rebase, hg pull --rebase또는 hg help rebase.


2
명령에이 조건을 추가하기 위해서는 다음과 같이 실행해야합니다. hg rebase -s o -d f
Simple-Solution

21

위의 답변이 OP의 목표를 달성하지 못한다고 생각합니다. OP의 목표는 작업 분기를 유지하는 것이 었습니다.

이 그래프 (그래프 로그 확장명을 사용하여 생성 된 그래프 로그에 대한 진지한 괴짜 사랑)로 시작한다고 가정 해 봅시다.

@  9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o  af630ccb4a80 default againagainagain  
| |
o |  98bdde5d2185 Feature 3 branch commit 1  feature3
|/
o  e9f850ac41da foo   

feature3 브랜치에 있고 다시 한 번 커밋에서 리베이스하고 싶다면 내가 실행한다는 것을 이해합니다 hg rebase -d default. 결과는 다음과 같습니다.

@  89dada24591e Feature 3 commit 2 tip 
|
o  77dcce88786d Feature 3 branch commit 1  
|
o  af630ccb4a80 default againagainagain  
|
o  e9f850ac41da foo  

임무 완수? 나는 그렇게 생각하지 않습니다. 문제는 feature3 브랜치의 커밋이 다시 한번 다시 기반을 잡았을 때 feature3 브랜치가 삭제되었다는 것 입니다. 내 커밋은 기본 지점으로 옮겨졌습니다. 처음에는 피하려고했습니다.

Git에서 결과는 다음과 같습니다.

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo

feature3 브랜치는 여전히 존재하고 두 커밋은 여전히 ​​feature3 브랜치에 있으며 기본적으로 보이지 않습니다. 작업 분기를 유지하지 않으면 이것이 기능적으로 병합과 어떻게 다른지 알 수 없습니다.

업데이트 : --keepbrancheshg rebase가 지원 하는 플래그를 발견했으며 모든 것이 okey-dokey라는 것을 기쁘게 생각합니다. 을 사용하여 hg rebase -d default --keepbranches나는 갈망했던 Git 동작을 정확하게 복제합니다. 나중에 두 개의 별칭이 있고 나는 아무도없는 사업처럼 생각하고 있습니다.


7
rebase에서 --keepbranches 플래그를 발견했습니다. 문제 해결됨. 이것이 내 코드 였지만 기본값으로 만들려고했지만 그저 나뿐입니다.
Jonathan Blackburn

1
위의 답변에 약간의 정보를 추가하면 도움이 될 것이라고 생각합니다.
HansMari

3

어떤 사람들은 모든 것을 반복해서 유지하는 것이 좋다고 생각하기 때문에 차후에 오픈 소스 프로젝트의 경우 합병으로 가득 찬 변경 사항을 받아들이고 개발을 반복하면 지저분한 메인 라인 개정 내역을 만들 수 있습니다. 개정 내역은 현재 버전이 어떻게 제공되는지 확인하는 데 유용하지 않습니다.

제출 된 변경 사항을 작성하지 않은 사람이 검토하기 전에 검토 한 경우에 적합합니다. 따라서 기본 라인에 적용되는 변경 사항은 일반적으로 디버그되어 작동합니다. 그런 다음 라인의 원점을 역 추적 할 때 그 일부가 변경되는 과정의 중간 지점이 아니라 모든 변경 사항을 볼 수 있습니다.

x265 기고자 페이지 에서는 작업중 인 변경 사항을 다시 커밋하여 제출 준비를하는 방법에 대해 설명 합니다. 하여 x265 프로젝트 . (TogitiseHG를 사용하여 커밋을위한 git gui 's stage / unstage diff hunk와 같은 개별 파일의 모든 변경 사항을 커밋하는 것은 포함).

프로세스는 업스트림 팁으로 hg를 업데이트 한 다음 작업 디렉토리에서 모든 변경 사항을 커밋하지 않는 것입니다. 제출하려는 내용의 일부가 아닌 것을 선반에 넣은 다음 멋진 커밋 메시지를 사용하여 나머지 커밋이 적절할 때까지 나머지를 나누십시오.

복사 / 붙여 넣기 한 다음 수정 한 패치 세트의 이전 반복에서 커밋 메시지를 편집 할 것입니다. 또는 이전 커밋 (Git 언어의 체리 선택)을 접목 한 다음 하나씩 수정하여 이전 커밋 메시지를 편집 시작점으로 얻을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.