source

Git: 구체적인 약속을 기반으로 하는 방법은 무엇입니까?

nicesource 2023. 7. 18. 21:47
반응형

Git: 구체적인 약속을 기반으로 하는 방법은 무엇입니까?

다른 지점의 헤드가 아닌 특정 커밋을 기반으로 합니다.

A --- B --- C          master
 \
  \-- D                topic

로.

A --- B --- C          master
       \
        \-- D          topic

대신에

A --- B --- C          master
             \
              \-- D    topic

어떻게 하면 그것을 달성할 수 있을까요?

원하는 커밋에 임시 분기를 만든 다음 간단한 형식으로 rebase를 사용하여 --to 매개변수를 사용하지 않도록 할 수 있습니다.

git branch temp master^
git checkout topic
git rebase temp
git branch -d temp

직접적인 접근 방식을 취할 수도 있습니다.

git checkout topic
git rebase <commitB>

"to" 옵션을 사용합니다.

git rebase --onto master^ D^ D

OR

git rebase --onto <commitB> <commitA> <commitD>

세 개의 마지막 인수는 다음을 의미합니다.

  • 대상(새 부모, 여기는 commitB),
  • start-after(현재-상위, 이동할 첫 번째 커밋의 상위),
  • 및 End-commit(이동할 마지막 커밋).

위의 jsz의 의견은 저에게 많은 고통을 덜어주었기 때문에, 다음은 제가 다른 약속 위에 커밋을 재배치/이동하는 데 사용해 온 단계별 리셉션입니다.

  1. 재배치(이동)할 분기의 이전 분기점을 찾습니다. 이전 분기점을 이전 상위라고 합니다.위의 예는 A입니다.
  2. 분기를 이동할 상위에서 커밋을 찾습니다. 새 상위라고 합니다.예제에서 그것은 B입니다.
  3. 이동하는 지점에 있어야 합니다.
  4. 기본 재배치 적용: git rebase --onto <new parent> <old parent>

위의 예에서는 다음과 같이 간단합니다.

   git checkout topic
   git rebase --onto B A

토픽 솔루션

일 수 .topic이미 체크아웃됨):

git rebase --onto B master
git rebase --onto master~1 master
git rebase --onto B A
git rebase --onto B C
git rebase --onto B

한다면topic체아웃않다니았습을 . 그냥 추가하시면 됩니다.topic다음과 같이 명령(마지막 명령 제외)에 적용됩니다.

git rebase --onto B master topic

또는 다음을 사용하여 지점을 먼저 확인하십시오.

git checkout topic

모든 커밋 문자열을 대상 커밋으로 재배치

설명서에서 발췌한 명령어의 기본 형식은 다음과 같습니다.

git rebase --onto <Target> [<Upstream> [<Branch>]]

<Branch>는 선택 사항이며 나머지 명령을 실행하기 전에 지정된 분기를 체크아웃하는 것이 전부입니다.기본값을 변경할 분기를 이미 체크아웃한 경우에는 이 항목이 필요하지 않습니다.로 "" " " " " 를 .<Upstream>를 지정하기 <Branch>오짓트는 당신이 지정하고 있다고 생각할 것입니다.<Upstream>.

<Target>일련의 커밋을 연결할 커밋입니다.분기 이름을 제공할 때는 해당 분기의 헤드 커밋을 지정하기만 하면 됩니다. <Target>이동할 커밋 문자열에 포함되지 않는 커밋일 수 있습니다.예:

A --- B --- C --- D         master
      \
       \-- X --- Y --- Z    feature

분기를 전체피분기이동면다음선수없다습니택할을려를 할 수 .X,Y,Z또는feature▁the로서<Target>모두 이동되는 그룹 내부의 커밋이기 때문입니다.

<Upstream>두 가지 다른 것을 의미할 수 있기 때문에 특별합니다.체크아웃된 분기의 상위 항목인 커밋인 경우, 컷포인트 역할을 합니다.제공한 은 제가제공한예, 이은모것아닙이다니든서에것이입니다.C,D또는master 커밋은 커밋모든후 뒤에 있습니다.<Upstream>체크아웃한 지점의 헤드가 이동할 때까지.

만약 만지면, 에약.<Upstream>이 상위 항목이 아닙니다. 그러면 Git는 체크아웃된 분기가 있는 공통 상위 항목을 찾을 때까지 지정된 커밋에서 체인을 백업합니다(찾을 수 없는 경우 중단됨). 경우에는 우의경우,<Upstream>B,C,D또는master모든 것이 커밋으로 이어질 것입니다.B커트 포인트 역할을 하는 <Upstream>. 는 그 자 가 선 는 경 지 않 우 웃 된 아 분 살 봅 펴 니 다 를 부 모 의 기 체 크 은 되 정 지 체 명 택 적 인 이 령 며 ▁which ▁is ▁at ▁of ▁branch ▁entering▁equival▁the▁out▁the다 ▁is ▁if ▁itself그it▁checked▁then▁of▁and니 ▁an봅펴it▁parent살▁g▁looks,▁the▁it를▁command모부자 이는 입력하는 것과 같습니다.master.

Git가 잘라내고 이동할 커밋을 선택했으므로 Git는 이 커밋을 적용합니다.<Target>대상에 이미 적용된 항목을 건너뜁니다.

흥미로운 예와 결과

이 시작점 사용:

A --- B --- C --- D --- E         master
            \
             \-- X --- Y --- Z    feature
  • git rebase --onto D A feature
    커밋을 합니다.B,C,X,Y,Z지는저를 D그리고 결국 건너뛰게 됩니다.B그리고.C이미 적용되었기 때문입니다.

  • git rebase --onto C X feature
    커밋을 합니다.Y그리고.Z지는저를 C커밋을 합니다.X

은 더간한해은입니다.git rebase <SHA1 of B> topic은 당신의 이은당위상작이동다니합관없이 에 있든지 상관없이 작동합니다.HEAD사실은.

Gitrebase 문서에서 이 동작을 확인할 수 있습니다.

<upstream>비교할 업스트림 분기입니다.기존 지점 이름뿐만 아니라 유효한 커밋일 수 있습니다.현재 분기에 대해 구성된 업스트림으로 기본 설정됩니다.


You might be thinking what will happen if I mention SHA1 of topic too in the above command ?

git rebase <SHA1 of B> <SHA1 of topic>

이것도 작동하지만 베이스를 재조정하면 작동하지 않습니다.Topic이렇게 생성된 새 분기를 가리킵니다.HEAD분리 상태가 됩니다.따라서 여기서 이전 버전을 수동으로 삭제해야 합니다.Topic그리고 rebase에 의해 생성된 새 분기에 새 분기 참조를 만듭니다.

기본 재배치가 매우 기본적이기 때문에, 여기 네스토르 밀랴예프의 대답이 확장되었습니다.애덤 다이미트룩의 답변에서 나온 jsz와 사이먼 사우스의 코멘트를 결합하면 다음과 같은 명령이 생성됩니다.topic분기여관분기이계없에부에서 masterA또는C:

git checkout topic
git rebase --onto <commit-B> <pre-rebase-A-or-post-rebase-C-or-base-branch-name>

않으면 커밋합니다).B).

예:

# if topic branches from master commit A:
git checkout topic
git rebase --onto <commit-B> <commit-A>
# if topic branches from master commit C:
git checkout topic
git rebase --onto <commit-B> <commit-C>
# regardless of whether topic branches from master commit A or C:
git checkout topic
git rebase --onto <commit-B> master

마지막 명령어는 제가 주로 사용하는 명령어입니다.

다을사용답추가를 사용하여 --onto:

저는 논쟁의 순서를 암기한 적이 없어서 다음과 같은 작은 도우미 스크립트를 작성했습니다.
Git: 한 베이스에서 다른 베이스로 분기를 재배치하고 다른 베이스의 커밋을 남깁니다.

용도:

moveBranch <branch> from <previous-base> to <new-base>

이 작업은 다음과 같습니다.

git rebase --onto "$ONTO" "$FROM" "$WHAT"

그 외에도, 유사한 목적으로 사용할 수 있는 한 가지 솔루션은 다음과 같습니다.cherry-pick일련의 커밋:

git co <new-base> 
git cherry-pick <previous-base>..<branch>
git branch -f branch

같은 효과가 더 적은 것입니다.은 " " " "에서 합니다.<previous-branch>그 자체로, 그래서 그것은 다음과 다음에 대한 약속을 포함하여 체리-링합니다.<branch>.

위에서 설명한 솔루션을 혼합하여 사용했습니다.

$ git branch temp <specific sha1>
$ git rebase --onto temp master topic
$ git branch -d temp

저는 읽고 이해하는 것이 훨씬 더 쉽다는 것을 알았습니다.승인된 솔루션은 병합 충돌(손으로 해결하기에는 너무 귀찮음)로 이어집니다.

$ git rebase temp
First, rewinding head to replay your work on top of it...
Applying: <git comment>
Using index info to reconstruct a base tree...
M       pom.xml
.git/rebase-apply/patch:10: trailing whitespace.
    <some code>
.git/rebase-apply/patch:17: trailing whitespace.
        <some other code>
warning: 2 lines add whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging pom.xml
CONFLICT (content): Merge conflict in pom.xml
error: Failed to merge in the changes.
Patch failed at 0001 <git comment>
The copy of the patch that failed is found in: .git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
git rebase --onto <commitB> <commitA> <commitD>

사실로 커밋commit, 마지매변커수밋로사개실막커▁as)을 합니다.<commitD>이름 (지점이름대신▁()대신이▁) ())topic지점을 .

    A --- B --- C          master
     \     \
      \     -- D'          <detached HEAD>
       \
        \-- D             topic

제외하고는...Git 2.36 이전의 경우에는 그렇지 않습니다.

언제git rebase $base $non_branch_commit(man)$base 조상또그이다.$non_branch_commitGit 2.36 (Q2 2022)으로 수정된 현재 분기를 수정했습니다.

commit bdff97a, 77ab58c(2022년 3월 18일)를 참조하십시오.john-cai
(주니오 C 하마노에 의해 합병 -- -- f818536, 2022년 3월 29일 커밋에서)

rebase세트REF_HEAD_DETACHcheckout_up_to_date()

신고자: 마이클 맥클라이먼
사인 오프 바이: 존 카이

어디서git rebase A B(man)B. 가 밋이아에서 하면 안 . 헤드가 분리된 것처럼 행동해야 합니다.B그리고 분리된 HEAD는 그 위에 다시 기반을 두었습니다.A.

그러나 버그는 현재 분기를 가리키도록 덮어씁니다.B,time,t제B는 의후니다의 입니다.A(즉, 기본 재배치는 결국 빨리 진행됩니다.)
원본 버그 보고서는 이 스레드를 참조하십시오.

의 콜 checkout_up_to_date()과 같습니다.

cmd_rebase()->checkout_up_to_date()-> -> -> reset_head() -> update_refs() -> update_refs()

Boid이며, 는 oid, rebase는 oid를 합니다.head_namerebase_optionsNULL.
은 이값 다의 멤를통버해이의 이 콜 됩니다.reset_head_opts 또시작기로 NULLupdate_refs().

그리고나서update_refs()을 확인하여 branchrops.dll을 합니다.
한다면ropts.branch이라NULL은 은것라고 부릅니다.update_ref()HEAD를 업데이트합니다.
그러나, 이 시점에서, 리베이스의 관점에서, 우리는 분리된 HEAD를 원합니다.
하지만, 그 이후로checkout_up_to_date()를 .RESET_HEAD_DETACH 깃발, update_ref()호출은 HEAD를 참조하고 가리키는 분기를 업데이트합니다.
우리는 대신 B에서 HEAD가 분리되기를 원합니다.

다음을 추가하여 이 버그를 수정합니다.RESET_HEAD_DETACH기어들어가다.checkout_up_to_date만약 B가 유효한 분기가 아니라면, 그래서 그것은 한 번.reset_head() 출들update_refs()은 은것라고 부릅니다.update_ref()와 함께REF_NO_DEREF이는 HEAD를 방어하고 HEAD가 가리키는 분기를 업데이트하는 대신 HEAD를 직접 업데이트합니다.

다른 방법이 있거나 둘 이상의 커밋으로 다시 이동하려는 경우.

다음은 다음과 같은 예입니다.n커밋 수:

git branch topic master~n

이 질문을 위해 이 작업을 수행할 수도 있습니다.

git branch topic master~1

명령어는 명은에작니다동합게벽하완에서 합니다.git version 2.7.4다른 버전에서는 테스트하지 않았습니다.

언급URL : https://stackoverflow.com/questions/7744049/git-how-to-rebase-to-a-specific-commit

반응형