development

힘내 : 특정 커밋에 리베이스하는 방법?

big-blog 2020. 7. 4. 09:28
반응형

힘내 : 특정 커밋에 리베이스하는 방법?


다른 지점의 HEAD가 아닌 특정 커밋에 리베이스하고 싶습니다.

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

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

대신에

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

어떻게하면 되나요?


원하는 커밋에 임시 브랜치를 만들어 --onto 매개 변수를 사용하지 않고 간단한 형식으로 rebase를 사용할 수 있습니다.

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

직접 접근 할 수도 있습니다.

git checkout topic
git rebase <commitB>

"onto"옵션을 사용하십시오 :

git rebase --onto master^ D^ D

위의 jsz의 의견은 많은 고통을 덜어주었습니다. 따라서 다른 커밋 위에 커밋을 리베이스 / 이동시키는 데 사용했던 단계별 레시피가 있습니다.

  1. 리베이스 (이동) 할 분기의 이전 분기점을 찾으십시오.이를 이전 상위라고합니다. 위의 예에서 A는
  2. 분기를 이동하려는 커밋을 새 부모라고 부릅니다. Exampe에서 그것은 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는 AS <Target>그 이후 모든 이동하는 그룹 내부 커밋이다.

<Upstream>두 가지를 의미 할 수 있기 때문에 특별합니다. 체크 아웃 된 브랜치의 조상 인 커밋이면 컷 포인트 역할을합니다. 내가 제공 한 예에서,이없는 어떤 것 C, D또는를 master. <Upstream>체크 아웃 된 지점의 헤드가 이동 될 때까지의 모든 커밋

However, if <Upstream> is not an ancestor, then git backs up the chain from the specified commit until if finds a common ancestor with the checked out branch (and aborts if it can't find one). In our case, an <Upstream> of B, C, D, or master will all result in commit B serving as the cut point. <Upstream> is itself an optional command and if it is not specified, then git looks at the parent of the checked out branch which is the equivalent of entering master.

Now that git has selected the commits it will cut and move, it applies them in order to <Target>, skipping any that are already applied to target.

Interesting Examples and Results

Using this starting point:

A --- B --- C --- D --- E         master
            \
             \-- X --- Y --- Z    feature
  • git rebase --onto D A feature
    커밋을 적용 B, C, X, Y, Z커밋하기 D및 스킵하지 않는 BC그들은 이미 적용되어 있기 때문이다.

  • git rebase --onto C X feature
    커밋 을 효과적으로 삭제하고 커밋 적용 Y하고 커밋합니다.ZCX


더 간단한 해결책은 git rebase <SHA1 of B> topic입니다. 이것은 당신의 위치에 관계없이 작동합니다 HEAD.

git rebase doc 에서이 동작을 확인할 수 있습니다

<upstream>비교할 업스트림 브랜치 기존 브랜치 이름뿐만 아니라 유효한 commit 일 수 있습니다 . 현재 분기에 대해 구성된 업스트림이 기본값입니다.


topic위의 명령에서 SHA1을 언급하면 ​​어떻게 될지 생각하고 있습니까?

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

This will also work but rebase then won't make Topic point to new branch so created and HEAD will be in detached state. So from here you have to manually delete old Topic and create a new branch reference on new branch created by rebase.


I've used a mixture of solutions described above:

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

I found it much easier to read and understand. The accepted solution lead me to a merge conflict (too lazy to fix by hand):

$ 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".

Since rebasing is so fundamental, here's an expansion of Nestor Milyaev's answer. Combining jsz's and Simon South's comments from Adam Dymitruk's answer yields this command which works on the topic branch regardless of whether it branches from the master branch's commit A or C:

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

Note that the last argument is required (otherwise it rewinds your branch to commit B).

Examples:

# 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

So the last command is the one that I typically use.


There is another way of doing it or if you wish to move back to more than just one commit.

Here is a an example to move back to n number of commits:

git branch topic master~n

For the sake of this question, this can also be done:

git branch topic master~1

The command works perfectly on git version 2.7.4. Haven't tested it on any other version.

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

반응형