2011-12-09 4 views
3

이 질문은 이전에 물어 보았을 것입니다. 그러나 시간을 찾고 있습니다.이미 리베이스 된 공개 저장소를 어떻게 처리합니까?

경험이 많은 git 사용자는 "이미 공개적으로 공개 된 리포지토리를 사용하지 마십시오!"라고 말할 것입니다. 그리고 맞습니다. 그러나 낙진을 다루는 정보는 보이지 않습니다. 나는 그것이 우리 자신을 갖기로되어 있지 않은 상황이라는 것을 알고 있지만 그것이 일어 났을 때 우리는 무엇을해야합니까?

Original: A--B--C--D--E--F 
My Repo: A--B--C--D 
        \ 
        X--Y--Z 
Rebased: A--B 
       \ 
       L--M--N--O 

그래서 나는 fetch, 맞아, 아주 간단해야 하는가? 그리고 ... 그러면 어떻게됩니까? `pull --rebase을 수행하면 C--D이 없어서 어느 시점에서 실패합니다. 실제로 발생할 수있는 오류는 무엇이며 어떻게 수정합니까?

+0

Git 2.0은 [내 대답은 아래] (http://stackoverflow.com/a/20423983/6309)에서 설명한 프로세스를 단순화합니다. 게시 한 병합 결과 그래프에 관한 – VonC

답변

3

git-rebase 맨 페이지의 "UPSTREAM REBASE로부터 복구"라는 섹션이 있습니다.이 섹션에서는이를 매우 잘 설명합니다.

가져 오기

구체적으로 살펴 보도록하겠습니다. 가져 오기만하면 원격 추적 지점을 업데이트하는 것뿐입니다. 즉 여전히 잘 작동 - 그것은 당신에게 비록 경고 줄 것이다 : (병합) 정상 또는 리베이스 여부, 통화가 내부적으로 가져 오기,

From <url>: 
+ abc123...def456 master -> origin/master (forced update) 

끌어 오기 당기는. 따라서 아직 가져 오지 않았다면 "강제 업데이트"경고이 표시됩니다. 이미 가져온 경우, 강제 업데이트 경고가 이전에 제공되었으므로 지금 경고 할 강제 업데이트가 없습니다. 큰 병합 보고서가 병합 후에 병합되면 강제 업데이트 경고를 놓칠 수도 있습니다. 페치 한 후 git-pull은 요청 된대로 병합 또는 리베이스를 호출합니다. 이것은 이 실제로 무서운 곳입니다. Git에 관한 한, 현재 CD은 로컬 커밋 일뿐입니다. 한순간에 출판 된 것은 중요하지 않습니다. 따라서 Git은 평소와 같이 병합/리베이스합니다.

병합 :

- A - B - L - M - N - O (origin/master) 
    \     \ 
    C - D - X - Y - Z - Q (master) 

REBASE : 커밋 C와 D의 제거는 나중에 다른 커밋 만드는 경우

이제
- A - B - L - M - N - O (origin/master) - C' - D' - X' - Y' - Z' (master) 

은, 둘 중 하나는 아주 잘, 충돌로 실행할 수 있습니다. 병목 현상은 사용자가주의해야 할 유일한 오류입니다. 그러나 변경 사항이 격리 된 경우 모든 것이 "잘"진행됩니다. 사용자가 알아 채지 못한다면, 사용자는이 히스토리를 계속 푸시 할 수 있으므로 제거 된 커밋을 다시 유도 할 수 있습니다! 때때로 이것은 비교적 양성 일 수 있습니다. 어쩌면 L은 실제로 커밋 메시지에서 오타가있는 C이고 MNO는 DEF와 동일하지만 다른 부모와 동일합니다. 그래서 C와 D를 다시 도입하는 것은 역사를 혼란스럽게하는 것 이상의 아무것도하지 않을 것입니다. 하지만 어쩌면 위험 할 수도 있습니다. 아마도 C를 삭제하면 끔찍한 버그가 수정되었을 것입니다. 그리고 방금 다시 소개되었습니다.

문제

방지

그리고 출판 역사를 다시 쓸 수있는 정말 좋은 생각입니다 이유입니다.가장 좋은 경우는 중복 된 커밋으로 끝나고, 최악의 경우는 모르는 사이에 모든 것을 어기는 것입니다. 따라서 문제가 발생하면 가장 먼저해야 할 일은 모두에게라고 알려주고 복구 방법을 안내하십시오. 다음으로 발행 된 모든 것을주의 깊게 모니터링하여 이전 커밋을 다시 입력하지 않도록합니다. 공용 저장소에서 가져 오는이 작업의 반대편에있는 경우, 안정적인 지점을 리베이스하지 못하도록하거나 유지할지를 말하면되기를 바랍니다. 신뢰할 수 없다면 병합/리베이스를 가져 오는 것이 아니라 강제로 가져 오는 것이 좋습니다. 이렇게하면 "강제 업데이트"메시지에주의하고 매우주의 깊게 진행할 수 있습니다. 로컬

다양 복구하는 방법의 세부 사항 복구

; 앞서 말한 맨 페이지를 권합니다. C가 L로 재 작성되었는지 (또는 D가 M으로 재 작성되었는지) 또는 완전히 새로운 커밋인지 여부와 재배치 또는 병합을 원하는지 여부에 따라 달라집니다. rebase하기를 원한다면 XYZ를 O에 rebasing하는 것만으로 충분합니다. 병합 할 경우, 당신도 B 또는 M에 XYZ을 리베이스 것, 다음 병합 O.

+0

: 병합베이스가 'A'대신 'A-B'가되어야합니까? – SebNag

2
당신은 (" How do I recover/resynchronise after someone pushes a rebase or a reset to a published branch?"에서와 같이)해야

:

이 시점에서
git checkout yourBranch 
git branch old-upstreamBranch D # BEFORE fetching! 

      E--F (origin/upstreamBranch) 
     /
A--B--C--D (old-upstreamBranch) 
      \ 
      X--Y--Z (yourBranch) 


git fetch 


    L--M--N--O (origin/upstreamBranch) 
    /
A--B--C--D (old-upstreamBranch) 
      \ 
      X--Y--Z (yourBranch) 

, 당신은 단순히 수 없습니다 다시 작성한 upstreamBranch 상단에 지점을 리베이스하십시오. upstreamBranch을 다시 작성했을 때 C 및 D가 명시 적으로 그대로 남아있게됩니다.

당신은 전에 단지yourBranch, 그리고 커밋을 리베이스해야합니다.

git rebase --onto origin/upstreamBranch old-upstreamBranch yourBranch 

       X--Y--Z (yourBranch) 
      /
    L--M--N--O (origin/upstreamBranch) 
    /
A--B--C--D (old-upstreamBranch) 



git branch -D old-upstreamBranch 

       X--Y--Z (yourBranch) 
      /
    L--M--N--O (origin/upstreamBranch) 
    /
A--B 

:하지만 With Git 2.0, all you will need to do is : 당신이 가져 오는 전에 old-upstreamBranch 태그를 넣어 이유

fork_point=$(git merge-base --fork-point origin/upstreamBranch yourBranch) 
# return D 
git rebase --onto origin/upstreamBranch $fork_point yourBranch 

을 더 이상은 "가져 오는 전에 지점

당신이 만약! 문제가 실현 git fetch, 재 작성된 업스트림 브랜치의 맨 위에 브랜치를 멋지게 리베이스 할 수 있습니다.


commit ad8261d 때문에 John Keeping (johnkeeping)에서, git rebase이 같은 새로운 --fork-point 옵션을 사용할 수 있습니다.

관련 문제