Search

잘 쓰면 아주 좋은 git-rebase onto 옵션

Date
2022/08/27
Tags
Git
Created by
git-rebase의 onto 옵션, 어떤 경우에 사용하는 것인가?
Table of Contents
Mermaid 다이어그램이 보이지 않을 경우, https://driip.notion.site/git-rebase-onto-3e2061788e6c4519be3555b5afeab30b 링크에서 읽어 주시면 감사하겠습니다.

기본적인 git-rebase에 대하여

git-rebase는 기본적으로 1개 또는 2개의 인자를 받는다. 전체 Signature는 git rebase <upstream> [<branch>]이다.
gitGraph commit id: "A" commit id: "B" branch topic commit id: "C" commit id: "D" checkout main commit id: "E" commit id: "F" commit id: "G"
Mermaid

1개의 인수를 전달하는 경우

Signature는 git rebase <upstream>이다.
가령 main branch에 topic branch를 rebase하고 싶다면, 현재 branch가 topic인 상황에서 git rebase main를 입력하면 된다.
$ git branch --show-current topic $ git rebase main Successfully rebased and updated refs/heads/topic.
Shell
gitGraph commit id: "A" commit id: "B" commit id: "E" commit id: "F" commit id: "G" branch topic commit id: "C'" commit id: "D'"
Mermaid

2개의 인수를 전달하는 경우

Signature는 git rebase <upstream> <branch>이다.
현재 branch가 topic이 아닌 상황에서 git rebase master topic을 입력해도 위와 똑같은 결과를 얻을 수 있다.
$ git rebase master topic Successfully rebased and updated refs/heads/topic.
Shell
gitGraph commit id: "A" commit id: "B" commit id: "E" commit id: "F" commit id: "G" branch topic commit id: "C'" commit id: "D'"
Mermaid
이는 결국 git switch <branch>git rebase <upstream>을 수행하는 것과 동치이다.

--onto <newbase> 옵션

git-rebase에는 다양한 옵션을 제공할 수 있는데, 그 중 하나가 --onto 옵션이다. 이를 사용할 경우 Signature는 git rebase --onto <newbase> <upstream> [<branch>]가 된다.
인자가 2개 내지는 3개로 늘어나서 당황스러울 수 있겠다. 이 옵션을 쉽게 설명하면, <newbase><upstream>이 동일한 커밋을 가리킨다고 인정하고, 현재 branch를 <newbase>에 rebase하는 것”이라 할 수 있겠다.
아래는 Git 공식 문서에서 제공하는 --onto 옵션을 사용하는 예시이다.

예시 1

다음과 같은 상황을 가정하자.
gitGraph commit id: "A" commit id: "B" branch next commit id: "C" commit id: "D" branch topic commit id: "E" commit id: "F" commit id: "G" checkout main commit id: "H" commit id: "I" commit id: "J"
Mermaid
topic branch를 main으로 rebase하고 싶다면 어떻게 하면 될까?

그냥 rebase

아마 통상적인 rebase로는 다음과 같이 원치 않았던 결과가 나올 것이다.
$ git branch --show-current topic $ git rebase main Successfully rebased and updated refs/heads/topic.
Shell
gitGraph commit id: "A" commit id: "B" branch next commit id: "C" commit id: "D" checkout main commit id: "H" commit id: "I" commit id: "J" branch topic commit id: "C'" commit id: "D'" commit id: "E" commit id: "F" commit id: "G"
Mermaid

rebase --onto

아마 우리가 원하는 결과는 아래와 같은 결과가 아니었을까? 이는 다음과 같이 --onto 옵션을 이용하면 만들 수 있다.
$ git branch --show-current topic $ git rebase --onto main next Successfully rebased and updated refs/heads/topic.
Shell
gitGraph commit id: "A" commit id: "B" branch next commit id: "C" commit id: "D" checkout main commit id: "H" commit id: "I" commit id: "J" branch topic commit id: "E'" commit id: "F'" commit id: "G'" checkout main
Mermaid

예시 2

이번에는 다음과 같은 상황을 가정하자.
gitGraph commit id: "A" commit id: "B" branch next commit id: "C" commit id: "D" branch topic commit id: "E" commit id: "F" commit id: "G"
Mermaid
이번에도 하고 싶은 건 똑같다. topic branch를 main으로 rebase하고 싶다면 어떻게 하면 될까?

그냥 rebase

gitGraph commit id: "A" commit id: "B" branch next commit id: "C" commit id: "D" checkout main branch topic commit id: "C'" commit id: "D'" commit id: "E" commit id: "F" commit id: "G"
Mermaid

rebase --onto

gitGraph commit id: "A" commit id: "B" branch next commit id: "C" commit id: "D" checkout main branch topic commit id: "E" commit id: "F" commit id: "G"
Mermaid

실전 예시

다음과 같은 상황을 가정하자.
Initial branch로 main branch가 존재한다.
main을 parent branch로 하는 dev branch가 존재한다.
dev를 parent branch로 하는 feat/1 branch가 존재한다.
위 상황과 더불어, 우리는 feat/1 branch에서 작업하고 있고, devmain branch는 수시로 commit이 추가되거나 다른 branch에 rebase될 수 있다고 가정하자.
gitGraph commit id: "A" commit id: "B" branch dev commit id: "C" commit id: "D" branch feat/1 commit id: "E" commit id: "F" commit id: "G"
Mermaid

단순한 rebase로 해결되는 상황

feat/1 branch에서 작업하던 도중, 이의 parent branch인 dev branch에 새 commit이 추가되었고, feat/1 branch에 이를 반영할 필요가 생겼다.
gitGraph commit id: "A" commit id: "B" branch dev commit id: "C" commit id: "D" branch feat/1 commit id: "E" commit id: "F" commit id: "G" checkout dev commit id: "H" commit id: "I"
Mermaid
보통 이런 경우는 단순한 rebase로 해결할 수 있다.
$ git branch --show-current feat/1 $ git rebase dev Successfully rebased and updated refs/heads/feat/1.
Shell
gitGraph commit id: "A" commit id: "B" branch dev commit id: "C" commit id: "D" commit id: "H" commit id: "I" branch feat/1 commit id: "E'" commit id: "F'" commit id: "G'" checkout dev
Mermaid

rebase --onto가 필요한 상황

위 상황에 이어, main branch에 새로운 commit이 추가되었다고 해 보자.
gitGraph commit id: "A" commit id: "B" branch dev commit id: "C" commit id: "D" commit id: "H" commit id: "I" branch feat/1 commit id: "E'" commit id: "F'" commit id: "G'" checkout main commit id: "J"
Mermaid
그리고 dev branch에서 해당 커밋이 필요해서 main branch에 rebase했다고 해 보자. 아마 다음과 같은 그림이 나올 것이다.
gitGraph commit id: "A" commit id: "B" checkout main branch feat/1 order: 2 commit id: "C" commit id: "D" commit id: "H" commit id: "I" commit id: "E'" commit id: "F'" commit id: "G'" checkout main commit id: "J" branch dev order: 1 commit id: "C'" commit id: "D'" commit id: "H'" commit id: "I'" checkout main
Mermaid
빨리 feat/1 branch를 어떻게든 해야 할 것만 같다. 우리가 해야 하는 것은 dev의 HEAD commit(I’)과 (feat/1의) I commit이 동일하다는 것을 인정하고, feat/1dev로 rebase하는 것”이다.
그리고 이는 rebase --onto로 해결할 수 있다.
$ git branch --show-current feat/1 $ git rebase --onto dev I Successfully rebased and updated refs/heads/feat/1.
Shell
gitGraph commit id: "A" commit id: "B" commit id: "J" branch dev commit id: "C'" commit id: "D'" commit id: "H'" commit id: "I'" branch feat/1 commit id: "E'" commit id: "F'" commit id: "G'" checkout main
Mermaid

References