ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • git local 브랜치에서 remote 브랜치를 병합할 때 옵션
    일찍 알았으면 좋았을 넓고 얕은 개발 지식 2024. 2. 4. 01:18

    개요

    Git을 사용할 때 리모트 저장소와 로컬 저장소 사이의 커밋 히스토리가 일치하지 않는 경우가 있습니다. 예를 들어, 여러분의 팀원이 리모트(원격) 저장소의 main 브랜치에 feature 브랜치를 병합했어요. 그리고 여러분은 리모트의 main브랜치와 로컬의 main브랜치를 동기화 하려고 로컬에서 리모트의 최신 변경 사항을 가져오기 위해 git pull 명령어를 실행합니다. 이때 Git은 리모트의 main브랜치와 로컬의main브랜치 이 두 가지 다른 커밋 히스토리를 어떻게 하나로 합칠지 결정해야합니다.

    병합 옵션

    Git은 이 상황을 자동으로 해결할 수 없어요. 개발자에게 어떤 방식으로 통합할지 선택하라는 메시지를 표시합니다. 옵션은 3가지입니다. 병합(merge), 리베이스(rebase), 또는 fast-forward 입니다. 각 옵션은 병합 과정에서 발생할 수 있는 충돌을 해결하고, 커밋 히스토리를 어떻게 기록할지에 대한 다른 접근 방식을 제공합니다. 아래의 메시지는 git이 개발자에게 어떤 옵션으로 병합할지 고를 수 있게 hint를 주는 메시지 입니다. 즉, 동기화가 안됐다는 의미입니다. 맨 아래에 보면 fatal이라고 치명적인 오류가 있다고 하네요.

    hint: You have divergent branches and need to specify how to reconcile them.
    hint: You can do so by running one of the following commands sometime before
    hint: your next pull:
    hint: 
    hint:   git config pull.rebase false  # merge
    hint:   git config pull.rebase true   # rebase
    hint:   git config pull.ff only       # fast-forward only
    hint: 
    hint: You can replace "git config" with "git config --global" to set a default
    hint: preference for all repositories. You can also pass --rebase, --no-rebase,
    hint: or --ff-only on the command line to override the configured default per
    hint: invocation.
    fatal: Need to specify how to reconcile divergent branches.

     

    여기서 한가지 알아둬야 할 것은 git pull 명령어를 입력하면 git fetch + git merge 동작을 한번에 실행합니다.
    git fetch로 먼저 리모트의 변경사항을 조회하고 로컬로 가져옵니다. 그리고 로컬과 리모트의 커밋 히스토리가 같고 변경사항이 있으면 merge 혹은 rebase를 하는데, 지금의 상황처럼 리모트 브랜치와 로컬 브랜치 히스토리가 다른 경우에 개발자한테 어떻게 할지 병합 옵션을 골라달라고 하는 것 입니다.
    git pull 메시지를 입력했을 때 동작하는 자세한 상황은 다음과 같습니다.

    1. git fetch 실행: 리모트 저장소의 최신 커밋들을 로컬 저장소로 가져오면서 리모트 저장소의 변경 사항을 조회합니다. 이 단계에서는 리모트 저장소의 메타데이터(커밋, 브랜치 정보 등)만 로컬에 업데이트되며, 실제 작업 디렉토리의 파일들은 변경되지 않습니다.
    2. 로컬과 리모트의 히스토리 비교: git fetch로 가져온 후, 로컬의 현재 브랜치와 리모트 브랜치의 커밋 히스토리를 비교합니다. 이때 로컬 브랜치와 리모트 브랜치 사이에 서로 다른 변경 사항이 존재하고, 이 변경 사항들이 직접적인 선형적인 관계가 아닌 경우(즉, 간단한 fast-forward가 불가능한 경우), 병합 과정에서 어떻게 처리할지 결정해야 합니다.
    3. 병합 옵션 선택 요청: 로컬과 리모트 브랜치의 히스토리가 서로 다르고 간단한 fast-forward 병합이 불가능한 경우, Git은 개발자에게 병합 과정에서 어떤 전략을 사용할지 결정하도록 요청합니다. 이때 merge, rebase, 또는 fast-forward only 중에서 선택할 수 있도록 메시지를 표시합니다.

    3가지 병합방법

    merge

    git config pull.rebase false를 설정하면 git pull 명령을 실행할 때 merge 방식이 기본적으로 사용됩니다. 이는 리모트 변경 사항을 현재 브랜치로 가져올 때 자동으로 병합 커밋을 생성하여 두 브랜치의 변경 사항을 통합합니다. 병합 커밋은 나중에 혹시나 과거의 상황으로 돌아가야할 때 유용하게 쓰일 수 있습니다. git revert 명령어를 사용하여 병합 커밋을 되돌리면, Git은 병합 당시의 변경 사항을 취소하는 새로운 커밋을 생성합니다. 이를 통해 병합 이전 상태로 코드를 안전하게 되돌릴 수 있으며, 이 과정은 프로젝트의 안정성을 유지하는 데 도움이 됩니다.

    rebase

    git config pull.rebase true를 설정하면 git pull 명령을 실행할 때 rebase 방식이 기본적으로 사용됩니다. 이는 리모트 변경 사항을 현재 브랜치에 적용한 후, 로컬 브랜치의 커밋을 리베이스하여 커밋 히스토리를 선형적으로 만듭니다. 병합 커밋은 생성되지않고 rebase의 - i (인터렉티브 옵션)을 사용해서 다수의 커밋을 소수로 합치거나, 히스토리를 깔끔하게 관리할 수 있습니다. git pull --rebase=interactive 또는 단축형으로 git pull -r -i 명령어를 쓸 수도 있지만 git fetch 이후에 git rebase -i를 별도로 실행하는것이 일반적인 패턴입니다.

    fast-foward

    git config pull.ff only를 설정하면 git pull 명령을 실행할 때만 fast-forward 병합이 수행됩니다. 이 설정은 리모트 변경 사항을 로컬로 가져올 때 별도의 병합 커밋 없이 브랜치 포인터(HEAD)를 최신 커밋으로 단순히 이동시킵니다. 만약 fast-forward가 불가능한 상황이라면, Git은 오류를 발생시키고 병합을 중단합니다.

    정리

    각각의 병합 방법은 팀의 워크플로우, 커밋 히스토리를 관리하는 방법, 그리고 개인의 선호에 따라 선택됩니다. 일반적으로, 깔끔한 히스토리를 유지하고 싶다면 rebase를, 모든 히스토리를 보존하고 싶다면 merge를, 간단한 업데이트에는 fast-forward를 사용할 수 있습니다.

Designed by Tistory.