ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [git] cherry-pick와 merge 및 rebase를 활용한 commit 내역 관리
    git 2024. 5. 26. 22:13
    반응형

    1. cherry pick 란?

    git docs를 찾아보면 cherry pick에 대해 Apply the changes introduced by some existing commits 라고 한다.

    docs description을 보면 무슨 말인지 더 헷갈리는 것 같다..

    업무에서 사용해보고 따로 공부해보면서 이해한 바로는 A브랜치로 B브랜치의 commit을 복사해주는 기능이다.

    예를 들어 feature/a나 feature/b의 commit 내역을 골라서 develop 브랜치에 적용해야하는 경우 사용한다.

     

    cf. 따로 테스트하면서 유용한 git 명령어 옵션들로는 --continue--abort가 있었다.

     

    1-1. cherry pick 사용하기

    C:\DEV\git_test>git checkout develop

     

    이 상황에서 feature/b1에 대한 커밋(033623a)을 develop 브랜치에 적용시켜보자.

    # git cherry-pick <target commit hash>
    C:\DEV\git_test>git cherry-pick 033623a

     

    * conflict가 발생할 수도 있다.

    Auto-merging main.py
    CONFLICT (content): Merge conflict in main.py
    error: could not apply 033623a... feauture/b1
    hint: After resolving the conflicts, mark them with
    hint: "git add/rm <pathspec>", then run
    hint: "git cherry-pick --continue".
    hint: You can instead skip this commit with "git cherry-pick --skip".
    hint: To abort and get back to the state before "git cherry-pick",
    hint: run "git cherry-pick --abort".

     

     

    conflict를 해결하고 아래 명령어들을 실행한다.

    C:\DEV\git_test>git add . 
    C:\DEV\git_test>git cherry-pick --continue

     

    그럼 터미널에서 Vim 편집기가 켜진다.

    feauture/b1
    
    # Conflicts:
    #       main.py
    #
    # It looks like you may be committing a cherry-pick.
    # If this is not correct, please run
    #       git update-ref -d CHERRY_PICK_HEAD
    # and try again.
    
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    #
    # Date:      Mon May 27 01:13:33 2024 +0000
    #
    # On branch develop
    # Your branch is up to date with 'origin/develop'.
    #
    # You are currently cherry-picking commit 033623a.
    #
    # Changes to be committed:
    #       modified:   main.py
    #
    ~
    ~
    ~
    .git/COMMIT_EDITMSG [unix] (11:57 27/05/2024)                                                                                                                                                                   1,1 All
    "/c/DEV/git_test/.git/COMMIT_EDITMSG" [unix] 24L, 544B

     

    commit message를 변경하지 않을 거라면, :wq를 입력해서 Vim 편집기를 빠져나온다.

     

    C:\DEV\git_test>git push

     

     


    2. merge 사용하기

    이 상황에서 develop 브랜치에 feature/b 브랜치를 merge한다면 어떻게 될까?

    C:\DEV\git_test>git checkout develop

     

     

    C:\DEV\git_test>git merge feature/b

     

    cf. conflict가 난다면 해결한다.

     

     

    C:\DEV\git_test>git add .
    C:\DEV\git_test>git merge --continue

     

    그럼 터미널에서 Vim 편집기가 켜진다.

    Merge branch 'feature/b' into develop
    
    # Conflicts:
    #       main.py
    #
    # It looks like you may be committing a merge.
    # If this is not correct, please run
    #       git update-ref -d MERGE_HEAD
    # and try again.
    
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    #
    # On branch develop
    # Your branch is up to date with 'origin/develop'.
    #
    # All conflicts fixed but you are still merging.
    #
    # Changes to be committed:
    #       modified:   main.py
    #
    ~
    ~
    ~
    ~
    ~
    .git/COMMIT_EDITMSG [unix] (12:13 27/05/2024)                                                                                                                                                                   1,1 All
    "/c/DEV/git_test/.git/COMMIT_EDITMSG" [unix] 22L, 510B

     

    commit message를 변경하지 않을 거라면, :wq를 입력해서 Vim 편집기를 빠져나온다.

     

    C:\DEV\git_test>git push

     

     


    3. rebase 란?

    이번 실험을 통해서도 merge 말고 rebase를 써야할 이유를 못 찾았다..

    관련 개념적 이해뿐만 아니라 어느 상황에 써야 merge보다 더 좋은지 모르겠으니 해당 개념은 여기를 참고하자.

    docs에서 제일 중요한 부분을 가져오자면,

    Rebase 의 위험성
    Rebase가 장점이 많은 기능이지만 단점이 없는 것은 아니니 조심해야 한다.
    그 주의사항은 아래 한 문장으로 표현할 수 있다.

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

    이 지침만 지키면 Rebase를 하는 데 문제 될 게 없다.
    하지만, 이 주의사항을 지키지 않으면 사람들에게 욕을 먹을 것이다.

    Rebase는 기존의 커밋을 그대로 사용하는 것이 아니라 내용은 같지만 다른 커밋을 새로 만든다.
    새 커밋을 서버에 Push 하고 동료 중 누군가가 그 커밋을 Pull 해서 작업을 한다고 하자.
    그런데 그 커밋을 git rebase 로 바꿔서 Push 해버리면 동료가 다시 Push 했을 때 동료는 다시 Merge 해야 한다.
    그리고 동료가 다시 Merge 한 내용을 Pull 하면 내 코드는 정말 엉망이 된다.

     

    위험성에 대해 읽어보면 협업하는 프로젝트에선 rebase보단 merge를 사용하는 게 더 좋을 것 같다..

     

    3-1. rebase 사용하기

    feature/b 브랜치를 재활용할 경우 head를 위로 올릴 필요 있다.

    이때 rebase를 이용한다.

    C:\DEV\git_test>git checkout feature/b

     

     

    # git rebase <target branch>
    C:\DEV\git_test>git rebase develop

     

     

    C:\DEV\git_test>git push

     


    4. feature/a 브랜치 merge? rebase? 실험

    해당 브랜치도 위와 같은 방법으로 merge 후 rebase하면 된다.

    실험삼아 rebase를 해보려고 했지만 commit내역마다 conflict를 해소해줘야하고 복잡해지는 것 같았다.

    이런 경우에는 merge 후 rebase를 통해 HEAD를 끌어 올리는거나 merge로만 해결하는 게 제일 깔끔한 것 같다.

     

     

    728x90
Designed by Tistory.