본문 바로가기
ETC/Git

[Git] Git branch / merge

by 컴돈AI 2023. 12. 13.

목차

    branch가 필요한 이유

    • 코드를 작성하다보면 원본 코드(정상작동하는 코드)를 수정하고 싶은 경우가 생깁니다. 하지만 이러한 경우 원본 코드를 직접 수정하게 되면, 원본 코드가 망가질 수 있는 위험성이 존재합니다. 
    • 이러한 경우를 대비하기 위해 원본 코드를 복사해서 복사본에서 작업하는 경우가 있습니다. 이렇게 코드를 직접 복사해도 되지만, git branch기능을 이용하면 손쉽게 복사본을 만들 수 있습니다.
      • branch는 프로젝트 복사본이라고 생각하면 이해하기 쉽습니다. (정확히 말하면 커밋(버전)의 복사본입니다.)
    • 또한 하나의 프로젝트에 대해서 여러 사람이 코드를 작성할 경우 기준이 되는 코드를 각각 사람들이 branch를 생성해서 협업을 할 때도 사용이 가능합니다.

    git branch

    •  branch 생성
      • git branch 브랜치명

    git switch

    • branch 이동
      • git switch 브랜치명
         
    • 현재 작업중인 브랜치는 git status를 통해 확인가능합니다.

    merge가 필요한 이유

    • branch를 이용해서 생성한 branch에서 코드를 수정하고 나면 원본 코드와 합쳐주는 작업이 필요합니다. 이때 사용하는 작업이 merge 작업입니다.
    • merge를 할 때 두 가지 엔딩이 존재
      • merge 성공
        • 원본 코드와 branch 코드가 다른 코드를 수정한 경우 정상 merge
      • merge 실패(=충돌,conflict)
        • 원본 코드와 branch 코드가 같은 코드를 수정한 경우 충돌(conflict) 발생
        • 충돌 시에는 코드를 비교해 보며 직접 수정해야 합니다.

    git merge

    • branch merge 하기
      • 기준이 되는 브랜치로 이동 (메인이 되는 브랜치, 예를 들면 git switch main)
        • git switch 기준브랜치
      • 기준이 되는 브랜치에서 아래 명령어 입력
        • git merge 합칠브랜치명 -m "커밋메시지"
    • 예시
      • main 브랜치와 feature 브랜치가 있다고 할 때 feature 브랜치에서 수정한 코드를 main 브랜치와 merge 하고 싶습니다. 현재 브랜치는 feature 브랜치입니다.
      • git switch main을 통해 기준이 되는 브랜치도 이동합니다.
      • git merge feature를 통해 feature 브랜치와 main 브랜치를 합쳐줍니다.

    충돌(conflict) 시 해결 방법

    • 충돌 시에는 코드를 비교해 보며 직접 수정해야 합니다.
    • 충돌 예시 
      • 두 브랜치의 차이점을 보여줍니다.
      • vscode 에디터를 사용할 경우 위버튼을 통해서 손쉽게 어떤 코드를 적용할지 설정해 줄 수 있습니다.
    • 코드를 수정한 뒤 git add와 git commit을 해주게 되면 merge가 완료되게 됩니다.

    merge의 다양한 방식

    3-way merge

    • 메인 브랜치에서 새로운 브랜치를 만든 뒤, 메인 브랜치와 새로운 브랜치에서 각각 코드를 고치고 git merge 하는 방식은 3-way merge 방식입니다. 
      • 즉, 각 브랜치 모두 신규 commit이 있는 경우 3-way merge라고 합니다.
    • 3-way merge 방식으로 merge를 진행하게 되면 merge 된 부분으로 기준 브랜치 태그만 이동하게 됩니다. (즉, merge 된 부분으로 new 브랜치 태그는 움직이지 않습니다.

    fast-forward merge

    • 메인 브랜치에서 새로운 브랜치를 만든 뒤, 메인 브랜치에는 신규 커밋이 없고 새로운 브랜치에만 신규 커밋이 있을 경우 git merge 하는 방식은 fast-forward merge 방식입니다.
      • 즉, 새로운 브랜치에만 신규 commit이 있을 경우 fast-forward merge라고 합니다.
    • fast-forward merge 방식은 메인 브랜치에 아무런 변화가 없기 때문에 그냥 새로운 브랜치에 main 브랜치라고 이름만 붙여주면 됩니다.
      • 만약 이 방법이 싫다면 다음 코드로 merge 해주면 됩니다. (3-way merge 방식으로 merge 됩니다.)
        • git merge --no-ff 브랜치명 -m "커밋메시지"

    rebase & fast-forward merge

    • 3-way merge 방식처럼 메인 브랜치에서 새로운 브랜치를 만든 뒤,메인 브랜치와 새로운 브랜치에서 각각 코드를 고친경우 사용하는 방식입니다.
    • 하지만, 3-way merge와 달리 새로운 브랜치의 시작점을 메인 브랜치의 최근 지점으로 옮긴 뒤(=rebase 한 뒤), fast-forward merge 방식으로 merge를 진행합니다.
      • rebase
        • rebase는 브랜치의 시작점을 다른 commit으로 옮겨주는 행위입니다.
        • 예시
          • commit2에서 생성된 새로운 브랜치에서 생성된 커밋들의 시작 지점을 메인 브랜치의 최근 지점인 commit3으로 옮기는 것을 rebase라고 합니다.
      • fast-forward merge
        • 이후 과정은 fast-forward merge 방식과 동일하게 진행되게 됩니다.
      • git switch 새로운브랜치
        git rebase main
        
        git switch main
        git merge 새로운브랜치
    • rebase를 왜 해주는 것일까요?
      • 3-way merge 방식으로 진행하게 되면 graph에 잔가지들이 많게 됩니다. (지저분함)
    • 하지만 브랜치 끼리 차이가 너무 많게 되면 rebase 할 경우 충돌이 많이 발생할 수 있는데 하나하나 모두 해결해주어야 합니다.
      • 먼저 충돌이 발생한 파일을 열어 충돌을 수동으로 해결합니다.
      • 수정된 파일 스테이징 (git add 수정된 파일명)
      • git rebase --continue 를 통해 리베이스를 계속 진행

    squash & merge

    • squash & merge 사용하는 이유
      • rebase에서 살펴본 것처럼 단순히 3-way merge만을 하게 되면 아래처럼 지저분해지게 됩니다.
      • 또한 각 브랜치에서 생성된 메시지들도 출력되어서 나오기 때문에 합쳐진 브랜치기준에서 쓸데없는 commit 내역들이 너무나도 많아질 수 있습니다.
      • rebase의 경우 한 줄로 이어지기는 하지만 새로운 브랜치에서 생성된 커밋 내용들은 쭉 이어서 나오게 됩니다.
      • 하지만 squash의 경우 새로운 브랜치에서 작업한 커밋내역들을 rebase처럼 이어주지 않고 커밋내역들을 하나의 커밋으로 main 브랜치에 커밋하게 됩니다. 
        • squash 브랜치에서 작업된 2가지 커밋 내역이 main브랜치에는 1개의 커밋으로 처리됐습니다. (아무리 많은 커밋 작업을 했더라도 main 브랜치에는 1개의 커밋으로 처리됩니다.)
      • 따라서 특정 브랜치에서 작업한 커밋 내역들은 중요하지 않고 결과만이 중요하다면 sqaush &merge를 사용할 수 있습니다.
    • 즉, rebase와 squash 모두 잔 branch가 main branch에 이어져서 지저분해지는 것을 방지하기 위해 사용됩니다. 하지만 rebase의 경우는 잔 branch에서 commit 된 내역들이 중요할 경우 사용하고, squash의 경우 잔 branch에서 commit 된 내역들을 하나도 중요하지 않고 오로지 결과만이 중요할 때 사용합니다.
    • git switch main
      git merge --squash 브랜치명
      git commit -m "커밋메시지"

    merge 후 branch 삭제 (or 잘못 만든 branch 삭제)

    • merge 후에 branch를 삭제해야 하는 이유는 무엇일까요?
      • 기능 개발이 완료되어 해당 브랜치의 변경 사항이 메인 브랜치에 병합이 되었다면, 더 이상 해당 기능 브랜치가 필요 없게 됩니다. 추후에 수정이 필요하다면 main 브랜치에서 다시 브랜치를 만들어서 수정하는 작업을 이용하면 됩니다.
      • 브랜치를 정리함으로써 현재 진행 중이거나 활성화된 작업에 대한 명확성을 제공합니다.
    • branch 삭제 과정
      • branch 삭제 전 ( 태그가 남아 있는 모습 )
      • branch 삭제 후
        • branch를 삭제한다고 해서 그동안의 기록이 삭제되는 것이 아닌 branch 태그 자체만 없어지게 되는 것입니다. 즉, 이제 해당 branch로 이동하지 못하게 됩니다.
    • branch 삭제 코드
      • git branch -d 브랜치이름
        git branch -D 브랜치이름
        • 병합이 완료된 브랜치 삭제 시엔 -d 
        • 병합하지 않은 브랜치 삭제 시엔 -D
          • 실수로 만든 브랜치의 경우 사용. -d는 반드시 병합된 브랜치만 삭제가 진행되기 때문에 병합되지 않은 브랜치는 -D를 통해 삭제해주어야 합니다.

    참고

    'ETC > Git' 카테고리의 다른 글

    [Git] GitFlow  (0) 2023.12.14
    [Git] GitHub 기본  (0) 2023.12.14
    [Git] commit 취소하기 (git revert) / commit reset하기 (git reset)  (0) 2023.12.14
    [Git] Git commit된 파일로 복구하기 (git restore)  (0) 2023.12.13
    [Git] Git 기초  (0) 2023.12.12