우리는 게시 된 작업을 절대로 리베이스해서는 안된다고, 위험하다는 등의 말을 들었습니다. 그러나 나는 리베이스 가 게시 된 경우 상황을 처리하는 방법에 대한 레시피가 게시 된 것을 보지 못했습니다 .
이제 저장소가 알려진 (가급적 작은) 그룹에 의해서만 복제되는 경우에만 실제로 가능하다는 점에 유의하십시오. 따라서 리베이스 또는 재설정을 푸시하는 사람은 다른 모든 사람에게 다음에주의를 기울여야한다고 알릴 수 있습니다. 술책(!).
내가 본 한 가지 분명한 솔루션은 로컬 커밋이없고 foo
리베이스 되는 경우 작동합니다 .
git fetch
git checkout foo
git reset --hard origin/foo
이것은 단순히 foo
원격 저장소에 따라 히스토리에 찬성하여의 로컬 상태를 버립니다 .
하지만 그 지점에서 상당한 지역적 변화를 일으킨다면 상황을 어떻게 다룰까요?
답변
푸시 된 리베이스 후에 다시 동기화하는 것은 대부분의 경우 그렇게 복잡하지 않습니다.
git checkout foo
git branch old-foo origin/foo # BEFORE fetching!!
git fetch
git rebase --onto origin/foo old-foo foo
git branch -D old-foo
즉. 먼저 원격 브랜치가 원래 있던 위치에 대한 북마크를 설정 한 다음이를 사용하여 해당 지점에서 리 기반 원격 브랜치로 로컬 커밋을 재생합니다.
Rebasing은 폭력과 같습니다. 문제가 해결되지 않으면 더 많이 필요합니다. ☺
물론 pre-rebase origin/foo
커밋 ID 를 찾아서 사용한다면 북마크 없이도 가능합니다 .
또한 가져 오기 전에 북마크를 만드는 것을 잊은 상황을 처리하는 방법이기도합니다 . 손실되는 것은 없습니다. 원격 분기에 대한 리플 로그를 확인하기 만하면됩니다.
git reflog show origin/foo | awk '
PRINT_NEXT==1 { print $1; exit }
/fetch: forced-update/ { PRINT_NEXT=1 }'
이것은 origin/foo
기록을 변경 한 가장 최근의 가져 오기 전에 가리키는 커밋 ID를 인쇄합니다 .
그런 다음 간단히
git rebase --onto origin/foo $commit foo
답변
내가 말하고 싶지만 상류 REBASE의 복구 힘내 – REBASE 매뉴얼 페이지 커버 섹션 거의 모든의를.
자신의 리베이스에서 복구하는 것과 실제로 다르지 않습니다. 하나의 브랜치를 이동하고 기록에있는 모든 브랜치를 새로운 위치로 리베이스합니다.
답변
자식과 함께 시작하는 것은 2014 년 1 분기 1.9 / 2.0, 당신은에 설명 된대로 다시 상류 지점에 그것을 리베이스하기 전에 이전 분기 원을 표시 할 필요가 없습니다 아리스토텔레스 Pagaltzis 의 대답 :
참조가 07d406b 커밋 과 d96855f 커밋 :
로
topic
만든 브랜치 에서 작업 한 후git checkout -b topic origin/master
원격 추적 브랜치의 기록을origin/master
되 감고 다시 빌드하여 다음과 같은 형태의 기록을 만들 수 있습니다.
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
여기서
origin/master
커밋에 포인트로 사용B3
,B2
,B1
지금은에 점B
, 그리고topic
때 백업의 지점은 정상에 시작되었다origin/master
이었다B3
.이 모드는의 reflog를 사용하여 분기점
origin/master
으로 찾기B3
때문에 다음topic
을 통해 업데이트 된 항목origin/master
을 기반으로 할 수 있습니다 .
$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
이것이 git merge-base
명령에 새로운 옵션이있는 이유입니다 .
--fork-point::
분기 (또는 이로 이어지는 모든 기록
<commit>
)가 다른 분기 (또는 참조)에서 분기 된 지점을 찾습니다<ref>
.
이것은 두 커밋의 공통 조상을 찾을뿐만 아니라 분기의 이전 화신에서 분기 된<ref>
역사를 확인하기 위해 의 리플 로그를 고려합니다<commit>
<ref>
.
”
git pull --rebase
“명령은 ”base
“가있는 경우에 대처하기 위해 분기 작업의 기반이 된 ” “분기 (일반적으로 원격 추적 분기)의 reflog 항목을 사용하여 리베이스되는 분기의 분기점을 계산합니다. 가지가 되 감고 재건되었습니다.
예를 들어, 기록이 다음과 같은 경우 :
- 현재의 끝은 ”
base
“지점에 있습니다B
만, 이전의 팁 예전 관찰을 불러오는B3
다음과B2
다음B1
, 커밋 현재에 도착하기 전에- 최신 “base”위에 리베이스되는 브랜치는 commit을 기반으로합니다
B3
.이 찾습니다
B3
“의 출력을 통해 이동하여git rev-list --reflog base
“(즉B
,B1
,B2
,B3
) 그것은 그 현재의 팁의 조상 커밋 찾을 때까지 ”Derived (topic)
“.내부적으로
get_merge_bases_many()
는 일회성으로 이것을 계산할 수 있습니다. ” ” 의 모든 역사적 팁을 병합하여 결과가되는 가상의 병합 커밋
사이의 병합 기반을 원할Derived
것base (origin/master)
입니다.
그러한 커밋이 존재하면 ”base
” 의 reflog 항목 중 하나와 정확히 일치하는 단일 결과를 얻어야합니다 .
힘내 2.1 (2014 년 3 분기)이이 기능이 더 강력하게 추가 할 것입니다 : 참조 1e0dacd 커밋 에 의해 존 키핑 ( johnkeeping
)
다음 토폴로지가있는 시나리오를 올바르게 처리하십시오.
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
어디:
B'
는B
패치와 동일하지 않은 수정 된 버전입니다B
.C*
및D*
패치와 동일한다C
과D
각각 잘못된 순서로 적용될 경우, 텍스트로 충돌;E
텍스트는D
.
정확한 결과 git rebase master dev
IS B
의 포크 포인트로 식별 dev
하고 master
, 그래서 C
, D
, E
필요에이 재생 될 것을 커밋이다 master
; 하지만, C
및 D
패치와 동일하다 C*
및 D*
최종 결과가되도록, 따라서 감소 될 수있다 :
o --- B' --- C* --- D* --- E <- dev
분기점이 식별되지 않은 경우 B
포함 된 분기 를 선택 B'
하면 충돌이 발생하고 패치와 동일한 커밋이 올바르게 식별되지 않은 경우 C
포함 D
(또는 동등하게 D*
)을 포함하는 분기 를 선택 하면 충돌이 발생합니다.
” --fork-point
“모드는 git rebase
Git 2.27 (2020 년 2 분기)에서 수정 된 2.20 시대에 C에서 명령을 다시 작성했을 때 퇴보했습니다.
참조는 f08132f 커밋 에 의해 (2019 12월 9일)를 Junio C 하마노 ( gitster
)을 .
(Merged by Junio C gitster
Hamano — in commit fb4175b , 27 Mar 2020)
rebase
:--fork-point
회귀 수정서명자 : Alex Torok
[jc : 수정 사항 수정 및 Alex의 테스트 사용]
서명자 : Junio C Hamano
”
git rebase --fork-point master
“은 (는) 잘 작동했습니다. 내부적으로 ”git merge-base --fork-point
” 라는 이름으로 짧은 참조 이름을 처리하는 방법을 알고 기본get_fork_point()
함수 를 호출하기 전에 전체 참조 이름으로 변경했습니다 .명령이 C로 다시 작성된 후에는 더 이상 해당되지 않습니다. 직접 내부 호출이
get_fork_point()
짧은 참조를 dwim하지 않기 때문입니다.“git merge-base”에서 사용되는 “refname 인수를 전체 참조 이름으로 변경”논리를 기본
get_fork_point()
함수로 이동하여 “git rebase”구현에서 함수의 다른 호출자가 동일한 방식으로 수정하도록합니다. 이 회귀.