Dev Ops/Git Git 사용법 VI
  • 728x90
    반응형



    Git 사용법




    Rebase 하기



    Git에서 한 브랜치에서 다른 브랜치로 합치는 방법으로는 두 가지가 있다.


    하나는 Merge 이고 다른 하나는 Rebase 다.



    Rebase 의 기초



    두 개의 브랜치로 나누어진 커밋 히스토리


    merge 명령을 사용하면 두 브랜치의 마지막 커밋 두 개(C3, C4)와 공통 조상(C2)을 사용하는 


    3-way Merge로 새로운 커밋을 만들어 낸다.


    나뉜 브랜치를 Merge 하기


    비슷한 결과를 만드는 다른 방식으로, C3 에서 변경된 사항을 Patch로 만들고 이를 다시 C4에 적용시키는 방법이 있다.


    Git에서는 이런 방식을 Rebase 라고 한다.


    위의 예제는 아래와 같은 명령으로 Rebase 한다.


    $ git checkout experiment

    $ git rebase maseter

    First, rewinding head to replay your work on top of it...

    Applying: added staged command


    일단 두 브랜치가 나뉘기 전인 공통 커밋으로 이동하고 나서 그 커밋 부터 지금 Checkout 한 브랜치가 가리키는 커밋까지


    diff를 차례로 만들어 어딘가에 임시로 저장해 놓는다.


    Rebase 할 브랜치가 합칠 브랜치가 가리키는 커밋을 가리키게 하고 아까 저장해 놓았던 변경사항을 차례대로 적용한다.


    C4의 변경사항을 C3에 적용하는 Rebase 과정


    그리고 나서 master 브랜치를 Fast-foward 시킨다.


    $ git checkout master

    $ git merge experiment


    Merge 와 Rebase 는 둘다 합치는 관점에서는 서로 다를 게 없다.


    하지만 Rebase 가 좀더 깨끗한 히스토리를 만든다.


    Rebase 한 브랜치의 Log를 살펴보면 히스토리가 선형이다.


    Rebase 는 보통 리모트 브랜치에 커밋을 깔끔하게 적용하고 싶을 때 사용한다.


    Rebase를 하든지 Merge를 하든지 최종 결과물은 같고 커밋 히스토리만 다르다는 것이 중요하다.



    Rebase 활용



    Rebase는 단순히 브랜치를 합치는 것만 아니라 다른 용도로 사용할 수 있다.


    server 브랜치를 만들어서 서버 기능을 추가하고 그 브랜치에서 다시 client 브랜치를 만들어 클라이언트 기능을 추가한다.


    마지막으로 server 브랜치로 돌아가서 몇 가지 기능을 더 추가한다.


    다른 토픽 브랜치에서 갈라져 나온 토픽 브랜치


    테스트가 덜 된 server 브랜치는 그대로 두고 client 브랜치만 master 로 합치려는 상황을 생각해 보자.


    server 와는 아무 관련이 없는 client 커밋은 C8, C9이다. 


    이 두 커밋을 master 브랜치에 적용하기 위해서 --onto 옵션을 사용하여 아래와 같은 명령을 실행한다.


    $ git rebase --onto master server client


    이 명령은 master 브랜치부터 server 브랜치와 client 브랜치의 공통 조상까지의 커밋을 


    client 브랜치 에서 없애고 싶을 때 사용한다.


    client 브랜치에서만 변경된 패치를 만들어 master 브랜치에서 client 브랜치를 기반으로 새로 만들어 적용한다.


    다른 토픽 브랜치에서 갈라져 나온 토픽 브랜치


    master 브랜치로 돌아가서 Fast-forward 시킬 수 있다.


    $ git checkout master

    $ git merge client


    master 브랜치를 client 브랜치 위치로 진행 시키기


    server 브랜치의 일이 다 끝나면 git rebase [basebranch] [topicbranch] 라는 명령으로 


    Checkout 하지 않고 바로 server 브랜치를 master 브랜치로 Rebase 할 수 있다.


    이 명령은 토픽(server) 브랜치를 Checkout 하고 베이스(master) 브랜치에 Rebase 한다.


    $ git rebase master server


    master 브랜치에 server 브랜치의 수정 사항을 적용


    그리고 나서 master 브랜치를 Fast-forward 시킨다.


    $ git checkout master

    $ git merge server


    모든 것이 master 브랜치에 통합됐기 때 문에 더 필요하지 않다면 client 나 server 브랜치는 삭제해도 된다.


    브랜치를 삭제해도 커밋 히스토리는 남아있다.


    $ git branch -d client

    $ git branch -d server


    최종 커밋 히스토리



    Rebase 위험성



    이미 공개 저장소에 Push 한 커밋을 Rebase 하지 마라


    Rebase는 기존의 커밋을 그대로 사용하는 것이 아니라 내용은 같지만 다른 커밋을 새로 만든다.


    새 커밋을 서버에 Push 하고 동료 중 누군가가 그 커밋을 Pull 해서 작업을 한다고 하자.


    그런데 그 커밋을  git rebases  로 바꿔서 Push 해버리면 동료가 다시 Push 했을 때 동료는 다시 Merge 해야 한다.


    그리고 동료가 다시 Merge 한 내용을 Pull 하면 코드가 엉망이 된다.



    Rebase 한 것을 다시 Rebase 하기



    어떤 팀원이 강제로 내가 한일을 덮어썼다고 하자.


    그러면 내가 했던 일이 무엇이고 덮어쓴 내용이 무엇인지 알아내야 한다.


    커밋 SHA 체크섬 외에도 Git는 커밋에 Patch 할 내용으로 SHA 체크섬을 한번 더 구한다.


    이 값은 patch-id 라고 한다.


    한 팀원이 다른 팀원이 의존하는 커밋을 없애고 Rebase 한 커밋을 다시 Push 함



    한 팀원이 다른 팀원이 의존하는 커밋을 없애고 Rebase 한 커밋을 다시 Push 한 상황에서 


    Merge 하는 대신  git rebase teamone/master   명령을 실행하면 Git는 아래와 같은 작업을 한다.


    - 현재 브랜치에만 포함된 커밋을 찾는다. (C2, C3, C4, C6, C7)

    - Merge 커밋을 가려낸다. (C2, C3, C4)

    - 이 중 덮어쓰지 않은 커밋들만 골라낸다. (C2, C3, C4 는 C4' 와 동일한 Patch 다)

    - 남은 커밋들만 다시 teamone/master 바탕으로 커밋을 쌓는다.


    결과를 확인해보면 같은 Merge를 다시 한다 같은 결과 대신 


    제대로 정리된 강제로 덮어쓴 브랜치에 Rebase 하기 같은 결과를 얻을 수 있다.


    같은 Merge를 다시 한다.

    강제로 덮어쓴 브랜치에 Rebase 하기

    동료가 생성했던 C4와 C4' 커밋 내용이 완전히 같은 때만 이렇게 동작된다.


    커밋 내용이 아예 다르거나 비슷하다면 커밋이 두 개 생긴다


    git pull 명령을 실행할 때 기본적으로 --rebase 옵션이 적용되도록 pull.rebase 설정을 추가할 수 있다.


     git config --global pull.rebase true  명령으로 추가 한다.


    Push 하기 전에 정리하려고 Rebase 하는 것은 괜찮다.


    절대 공개하지 않고 혼자 Rebase 하는 경우도 괜찮다. 


    하지만 이미 공개하여 사람들이 사용하는 커밋을 Rebase 하면 틀림없이 문제가 생긴다.


    git pull --rebase 로 문제를 미리 방지할 수 있다는 것을 함께 공유 바란다.








    728x90
    반응형

    'Dev Ops > Git' 카테고리의 다른 글

    Git for windows server 2012 R2  (0) 2018.06.26
    Git 서버 I  (0) 2018.06.26
    Git 사용법 V  (0) 2018.06.22
    Git 사용법 IV  (0) 2018.06.20
    Git 사용법 III (되돌리기/수정 파일 되돌리기/Pull/Fetch/tag)  (0) 2018.06.19
상단으로