development

누군가가 게시 된 브랜치에 리베이스 또는 재설정을 푸시 한 후 복구 / 재 동기화하려면 어떻게해야합니까?

big-blog 2020. 9. 19. 11:47
반응형

누군가가 게시 된 브랜치에 리베이스 또는 재설정을 푸시 한 후 복구 / 재 동기화하려면 어떻게해야합니까?


우리는 게시 된 작업을 절대로 리베이스해서는 안된다고, 위험하다는 등의 말을 들었습니다. 그러나 나는 리베이스 게시 될 경우 상황을 처리하는 방법에 대한 레시피가 게시 된 것을 보지 못했습니다 .

이제 저장소가 알려진 (가급적 작은) 그룹에 의해서만 복제 된 경우에만 실제로 가능하다는 점에 유의하십시오. 따라서 리베이스 또는 재설정을 푸시하는 사람은 다른 모든 사람에게 다음에주의를 기울여야 함을 알릴 수 있습니다. 술책(!).

내가 본 한 가지 확실한 솔루션은 로컬 커밋이없고 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

즉. 먼저 원격 브랜치가 원래 있던 위치에 대한 북마크를 설정 한 다음이를 사용하여 해당 지점에서 리 기반 원격 브랜치로 로컬 커밋을 재생합니다.

리베이스는 폭력과 같습니다. 문제가 해결되지 않으면 더 많이 필요합니다.

물론 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 매뉴얼 페이지 커버 섹션 거의 모든의를.

자신의 리베이스에서 복구하는 것과 실제로 다르지 않습니다. 하나의 브랜치를 이동하고 기록에있는 모든 브랜치를 새로운 위치로 리베이스합니다.


자식부터는 Q1 2014 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::

Find the point at which a branch (or any history that leads to <commit>) forked from another branch (or any reference) <ref>.
This does not just look for the common ancestor of the two commits, but also takes into account the reflog of <ref> to see if the history leading to <commit> forked from an earlier incarnation of the branch <ref>.


The "git pull --rebase" command computes the fork point of the branch being rebased using the reflog entries of the "base" branch (typically a remote-tracking branch) the branch's work was based on, in order to cope with the case in which the "base" branch has been rewound and rebuilt.

For example, if the history looked like where:

  • the current tip of the "base" branch is at B, but earlier fetch observed that its tip used to be B3 and then B2 and then B1 before getting to the current commit, and
  • the branch being rebased on top of the latest "base" is based on commit B3,

it tries to find B3 by going through the output of "git rev-list --reflog base" (i.e. B, B1, B2, B3) until it finds a commit that is an ancestor of the current tip "Derived (topic)".

Internally, we have get_merge_bases_many() that can compute this with one-go.
We would want a merge-base between Derived and a fictitious merge commit that would result by merging all the historical tips of "base (origin/master)".
When such a commit exist, we should get a single result, which exactly match one of the reflog entries of "base".


Git 2.1 (Q3 2014) will add make this feature more robust to this: see commit 1e0dacd by John Keeping (johnkeeping)

correctly handle the scenario where we have the following topology:

    C --- D --- E  <- dev
   /
  B  <- master@{1}
 /
o --- B' --- C* --- D*  <- master

where:

  • B' is a fixed-up version of B that is not patch-identical with B;
  • C* and D* are patch-identical to C and D respectively and conflict textually if applied in the wrong order;
  • E depends textually on D.

The correct result of git rebase master dev is that B is identified as the fork-point of dev and master, so that C, D, E are the commits that need to be replayed onto master; but C and D are patch-identical with C* and D* and so can be dropped, so that the end result is:

o --- B' --- C* --- D* --- E  <- dev

If the fork-point is not identified, then picking B onto a branch containing B' results in a conflict and if the patch-identical commits are not correctly identified then picking C onto a branch containing D (or equivalently D*) results in a conflict.

참고URL : https://stackoverflow.com/questions/4084868/how-do-i-recover-resynchronise-after-someone-pushes-a-rebase-or-a-reset-to-a-pub

반응형