Git 브랜치: 개념부터 실전 전략까지

코드 버전 관리의 핵심, 브랜치 다루기

Git 브랜치의 개념, 주요 명령어(생성, 전환, 병합, 삭제), 원격 브랜치 관리, 충돌 해결, 다양한 브랜치 전략 및 푸시 워크플로우를 상세히 알아본다.

Engineering
Git
저자

Kwangmin Kim

공개

2023년 05월 03일

1 Git 브랜치 개요

Git 브랜치는 프로젝트의 독립적인 작업과 효율적인 협업을 가능하게 하는 핵심 기능이다. 브랜치를 통해 여러 개발자가 동시에 다른 기능을 개발하거나 버그를 수정할 수 있으며, 코드의 안정성을 유지하면서 체계적인 코드 관리가 가능하다.

2 기본 브랜치 명령어

Git 브랜치 관련 주요 명령어는 다음과 같다. 이를 통해 브랜치를 생성, 확인, 전환, 병합, 삭제하는 과정을 통해 코드 관리를 체계적으로 수행할 수 있다.

2.1 브랜치 생성

새로운 기능 개발이나 버그 수정 등 독립적인 작업을 시작할 때 새로운 브랜치를 생성한다.

git branch feature/login-page
# 출력: 없음 (성공 시 아무것도 출력되지 않는다)

# 생성 후 목록 확인
git branch
# 출력 예시:
#   feature/login-page
# * main              ← * 가 현재 브랜치

브랜치를 만든다고 자동으로 그 브랜치로 이동되지 않는다. git branch <이름> 은 브랜치를 생성만 한다.

2.2 브랜치 이동 (전환)

작업하려는 브랜치로 전환한다. Git 버전에 따라 checkout 또는 switch 명령어를 사용한다.

# 브랜치 전환
git switch feature/login-page
# 출력 예시:
# Switched to branch 'feature/login-page'

# 생성 + 전환 동시에 (가장 많이 쓰는 패턴)
git switch -c feature/new-feature
# 출력 예시:
# Switched to a new branch 'feature/new-feature'

# 구 버전 (Git 2.23 미만)
git checkout feature/login-page
# 출력 예시:
# Switched to branch 'feature/login-page'

git checkout -b feature/new-feature
# 출력 예시:
# Switched to a new branch 'feature/new-feature'

-c (switch) 또는 -b (checkout) 옵션으로 브랜치 생성과 전환을 동시에 할 수 있어 실무에서 자주 사용된다.

2.3 브랜치 병합

특정 브랜치에서 완료된 작업을 다른 브랜치(주로 main 또는 develop)로 통합할 때 사용한다.

git merge <branch_name_to_merge>  

예를 들어, feature/login-page 브랜치의 변경 사항을 현재 브랜치(예: main)로 병합하려면 먼저 main 브랜치로 이동한 후 다음 명령어를 실행한다.

# 1. main 브랜치로 이동 (이미 main 브랜치라면 생략 가능)  
git switch main
# 출력 예시:
# Switched to branch 'main'
# Your branch is up to date with 'origin/main'.

# 2. feature/login-page 브랜치 병합  
git merge feature/login-page
# 출력 예시 1 — Fast-forward 병합 (충돌 없음):
# Updating a1b2c3d..b2c3d4e
# Fast-forward
#  src/login.py   | 45 ++++++++++++++++++++++++++++++++++++++++++++
#  src/auth.py    |  8 ++++++++
#  2 files changed, 53 insertions(+)

# 출력 예시 2 — Merge commit (두 브랜치 모두 새 커밋이 있을 때):
# Merge made by the 'ort' strategy.
#  src/login.py   | 45 ++++++++++++++++++++++++++++++++++++++++++++
#  1 file changed, 45 insertions(+)

Fast-forward 란 현재 브랜치(main)에 새 커밋이 없고 병합 대상 브랜치만 앞서 있을 때 발생한다. 별도의 병합 커밋 없이 포인터만 이동한다. 두 브랜치 모두 새 커밋이 있으면 병합 커밋(Merge commit)이 생성된다.

2.4 브랜치 삭제

더 이상 필요 없는 브랜치를 삭제하여 프로젝트를 깔끔하게 관리한다. 로컬 브랜치와 원격 브랜치 삭제 방법이 다르다.

2.4.1 로컬 브랜치 삭제

개발자의 로컬 컴퓨터에 생성된 브랜치를 삭제한다.

git branch -d <local_branch_name> # 병합된 브랜치 삭제  
git branch -D <local_branch_name> # 병합되지 않은 브랜치 강제 삭제  
git branch -d feature/login-page
# 출력 예시:
# Deleted branch feature/login-page (was b2c3d4e).

# 병합하지 않은 브랜치 강제 삭제
git branch -D feature/wip-experiment
# 출력 예시:
# Deleted branch feature/wip-experiment (was c3d4e5f).

-d 는 이미 병합된 브랜치만 삭제한다. 병합하지 않은 브랜치를 -d 로 삭제하려 하면 다음 에러가 발생한다:

error: The branch 'feature/wip-experiment' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature/wip-experiment'.

해석: “이 브랜치는 아직 병합되지 않았다. 삭제하면 해당 커밋들이 사라진다. 정말 삭제하려면 -D 를 사용하라.”

2.4.2 원격 브랜치 삭제

GitHub와 같은 원격 저장소에 있는 브랜치를 삭제한다.

git push origin --delete <remote_branch_name>  

예시: 원격에서 feature/login-page 브랜치 삭제

git push origin --delete feature/login-page
# 출력 예시:
# To https://github.com/username/my_project.git
#  - [deleted]         feature/login-page

2.4.3 원격 브랜치 삭제 후 로컬 정리

원격에서 브랜치가 삭제된 후, 로컬 저장소에도 해당 정보를 반영하고 정리할 필요가 있다.

  1. 로컬에서도 해당 브랜치 삭제: 만약 로컬에 동일한 이름의 브랜치가 있다면 직접 삭제한다.
    bash git branch -d <branch_name>
  2. 삭제된 원격 브랜치 정보 로컬 반영 (Pruning): 원격 저장소에서 삭제된 브랜치에 대한 참조를 로컬에서 정리한다.
    bash git fetch --prune # 또는 git fetch -p
    이 명령어는 origin/<remote_branch_name>과 같이 더 이상 원격에 존재하지 않는 브랜치에 대한 로컬 참조를 제거한다.

2.5 브랜치 목록 확인

로컬 및 원격 브랜치 목록과 현재 상태를 확인한다.

git branch  
# 출력 예시:
#   develop
#   feature/login-page
# * main              ← * 가 현재 HEAD 위치

git branch -r  
# 출력 예시:
#   origin/HEAD -> origin/main
#   origin/develop
#   origin/feature/login-page
#   origin/main

git branch -a  
# 출력 예시:
#   develop
#   feature/login-page
# * main
#   remotes/origin/HEAD -> origin/main
#   remotes/origin/develop
#   remotes/origin/feature/login-page
#   remotes/origin/main

git branch -vv  
# 출력 예시:
#   develop            a1b2c3d [origin/develop] feat: Add dev environment
#   feature/login-page b2c3d4e [origin/feature/login-page: ahead 2] feat: Add login UI
# * main               c3d4e5f [origin/main] Merge pull request #5

git branch -vv 에서 ahead 2 는 로컬 브랜치가 원격보다 2개 커밋 앞서 있다는 의미 — 아직 push 하지 않은 커밋이 2개 있다. behind 1 이면 원격에 새 커밋이 있는데 아직 pull 하지 않은 것이다.

원격 저장소의 최신 상태를 가져온 후 전체 브랜치를 확인하는 예시는 다음과 같다.

git fetch --all # 모든 원격 저장소의 최신 상태를 가져옴  
git branch -a   # 로컬 및 원격의 모든 브랜치를 확인함  

3 원격 브랜치 관리

3.1 원격 브랜치 추적 (Tracking)

원격 저장소에 있는 특정 브랜치를 기반으로 로컬 브랜치를 생성하고, 해당 원격 브랜치를 추적하도록 설정한다. 이렇게 하면 git pull, git push 명령을 실행할 때 로컬 브랜치가 어떤 원격 브랜치와 통신해야 하는지 알 수 있다.

# 방법 1: 원격 브랜치와 동일한 이름으로 로컬 브랜치 생성 및 추적  
git checkout --track origin/<remote_branch_name>  

# 방법 2: 다른 이름으로 로컬 브랜치 생성 및 특정 원격 브랜치 추적  
git checkout -b <local_branch_name> origin/<remote_branch_name>  

설명:

  • <local_branch_name>: 로컬에서 생성할 새로운 브랜치 이름.
  • origin/<remote_branch_name>: 추적할 원격 저장소(기본적으로 origin)의 브랜치 이름.

사용 예시: 원격의 feature/new-feature 브랜치를 my-new-feature라는 로컬 브랜치로 생성하고 추적하려면 다음과 같이 한다.

git checkout -b my-new-feature origin/feature/new-feature  

만약 로컬 브랜치와 원격 브랜치 이름을 동일하게 하려면 다음과 같이 간단히 할 수 있다.

git switch feature/new-feature # Git 2.23+  
# 또는 git checkout feature/new-feature  
# 위 명령어는 로컬에 feature/new-feature 브랜치가 없고,   
# 원격(origin)에만 해당 이름의 브랜치가 하나 있을 때 자동으로 추적 관계를 설정하며 로컬 브랜치를 생성한다.  

3.2 업스트림 브랜치 설정 및 푸시

로컬 브랜치의 변경 사항을 원격 저장소에 푸시할 때, 해당 로컬 브랜치가 어떤 원격 브랜치와 연결되어야 하는지 명시해야 한다. 이를 “업스트림(upstream) 브랜치 설정”이라고 한다.

3.2.1 새로운 로컬 브랜치를 처음 푸시할 때

새로운 로컬 브랜치를 만들고 작업을 완료한 후 처음 원격 저장소로 푸시할 때는 업스트림 정보를 함께 설정해주는 것이 일반적이다.

git push --set-upstream origin <local_branch_name>  
# 줄여서 git push -u origin <local_branch_name>  

이 명령어는 다음 두 가지 작업을 수행한다:

  1. 로컬 브랜치 <local_branch_name>의 내용을 origin 원격 저장소에 동일한 이름의 브랜치로 푸시한다. (만약 원격에 해당 브랜치가 없다면 새로 생성된다.)
  2. 로컬 브랜치 <local_branch_name>이 원격 저장소 origin<local_branch_name> 브랜치를 추적하도록 업스트림 관계를 설정한다.

사용 예시: feature/submit-button 로컬 브랜치를 원격에 푸시하고 업스트림으로 설정하려면 다음과 같이 한다.

git push -u origin feature/submit-button  

이렇게 한번 업스트림 관계를 설정하고 나면, 이후 해당 브랜치에서는 git pushgit pull 명령어만으로도 Git이 자동으로 연결된 원격 브랜치와 통신한다.

3.2.2 현재 브랜치의 업스트림 연결 상태 확인

git branch -vv  

이 명령어를 실행하면 각 로컬 브랜치 옆에 어떤 원격 브랜치를 추적하고 있는지 (예: [origin/main]) 표시된다.

4 충돌 해결 (Merge Conflict)

브랜치를 병합하는 과정에서 동일한 파일의 같은 부분을 여러 브랜치에서 다르게 수정한 경우 “병합 충돌(merge conflict)”이 발생할 수 있다.

충돌이 발생하면 Git은 자동으로 병합을 멈추고 개발자에게 충돌을 해결하도록 요청한다. 충돌이 발생한 파일은 다음과 같은 형태로 표시된다.

<<<<<<< HEAD  
현재 브랜치(예: main)의 내용  
=======  
병합하려는 브랜치(예: feature/login-page)의 내용  
>>>>>>> feature/login-page  

충돌 해결 과정:

  1. 충돌 파일 확인: git status 명령으로 충돌이 발생한 파일 목록을 확인한다.

    git status
    # 출력 예시:
    # On branch main
    # You have unmerged paths.
    #   (fix conflicts and run "git commit")
    #   (use "git merge --abort" to abort the merge)
    #
    # Unmerged paths:
    #   (use "git add <file>..." to mark resolution)
    #         both modified:   src/app.py
    #
    # no changes added to commit (use "git add" and/or "git commit -a")

    both modified 로 표시된 파일이 충돌 파일이다.

  2. 충돌 내용 수정: 해당 파일을 열어 <<<<<<<, =======, >>>>>>> 마커를 참고하여 원하는 최종 코드로 직접 수정한다. 마커들도 함께 제거해야 한다.

  3. 수정된 파일 스테이징: 충돌을 해결한 파일을 git add 명령으로 스테이징한다.
    bash git add src/app.py

  4. 병합 커밋 완료: 모든 충돌을 해결하고 파일을 스테이징한 후, git commit 명령으로 병합을 완료한다.

    git commit
    # 에디터가 열리며 자동으로 아래 메시지가 입력되어 있다:
    # Merge branch 'feature/login-page' into main
    #
    # Conflicts:
    #         src/app.py
    #
    # # It looks like you may be committing a merge.
    # # If this is not correct, please run
    # #   git update-ref -d MERGE_HEAD
    # (에디터 저장 후 종료하면 병합 완료)

    저장 후 에디터를 닫으면 다음과 같이 출력된다:

    [main d4e5f6a] Merge branch 'feature/login-page' into main
힌트

병합 중 충돌이 너무 복잡하면 git merge --abort 로 병합 전 상태로 되돌릴 수 있다. rebase 중 충돌이 발생했다면 충돌 해결 후 git rebase --continue 를 사용한다.

5 브랜치 병합 예시

5.1 시나리오 1: dev-yjlee5 브랜치의 변경 사항을 main 브랜치로 병합하기

  1. 병합 대상 브랜치(main)로 이동:
    bash git switch main

  2. 원격 dev-yjlee5 브랜치의 최신 내용 가져오기 (선택 사항, 로컬에 최신 내용이 없다면):
    bash git fetch origin dev-yjlee5 # 이 명령은 원격 브랜치의 내용을 가져와 로컬에 origin/dev-yjlee5 로 업데이트한다. # 실제 병합은 로컬에 있는 브랜치를 기준으로 한다.

  3. dev-yjlee5 (또는 origin/dev-yjlee5)를 main 브랜치에 병합:

    # 만약 dev-yjlee5가 로컬에도 있고 최신 상태라면:  
    git merge dev-yjlee5  
    
    # 만약 로컬 dev-yjlee5 대신 원격의 최신 내용을 바로 병합하고 싶다면:  
    # (이미 fetch를 통해 origin/dev-yjlee5가 최신 상태여야 함)  
    git merge origin/dev-yjlee5   
  4. 충돌 해결: 충돌 발생 시 위에서 설명한 충돌 해결 과정을 따른다.

  5. 병합 결과 원격 저장소에 푸시:
    bash git push origin main

5.2 시나리오 2: main 브랜치의 변경 사항을 dev-yjlee5 브랜치로 병합하기 (최신 상태 유지)

  1. 작업 브랜치(dev-yjlee5)로 이동:
    bash git switch dev-yjlee5
  2. 원격 main 브랜치의 최신 내용 가져오기:
    bash git fetch origin main
  3. origin/maindev-yjlee5 브랜치에 병합:
    bash git merge origin/main
  4. 충돌 해결: 충돌 발생 시 충돌 해결 과정을 따른다.
  5. 병합 결과 원격 저장소에 푸시:
    bash git push origin dev-yjlee5

5.3 작업 워크플로우

5.3.1 운영 코드 작업 및 팀 리뷰 요청

# 현재 작업 브랜치를 팀 리뷰용 브랜치로 변경  
git switch feature/token-processor-improvements  

# 운영 코드 수정 (예: 8_token_analyzer/token_processor.py)  
# ... 코드 수정 ...  

# 변경 사항 스테이징 및 커밋  
git add 8_token_analyzer/token_processor.py  
git commit -m "feat: 토큰 분석기 성능 개선"  

# 원격 저장소에 푸시하여 팀원들에게 리뷰 요청  
git push origin feature/token-processor-improvements   

5.3.2 개인 실험 또는 파일 백업

# 개인 작업용 브랜치로 변경  
git switch personal/kmkim-workspace  

# 개인 폴더(kmkim/)에 파일 추가 또는 수정  
# ... 개인 작업 ...  

# 변경 사항 스테이징 및 커밋  
git add kmkim/  
git commit -m "개인 작업: 새로운 아이디어 스케치 및 자료 백업"  

# 원격 저장소에 푸시하여 개인 작업 내용 백업  
git push origin personal/kmkim-workspace  

5.3.3 다른 장소에서 개인 작업 이어가기

# 프로젝트 클론 (처음 작업 환경을 설정하는 경우)  
git clone https://github.com/SeegeneDevelopmentPlatform/data_standardization.git  
cd data_standardization  

# 개인 작업용 브랜치로 변경하여 작업 내용 복원  
git switch personal/kmkim-workspace   
# 또는 git checkout personal/kmkim-workspace (원격에만 있다면 추적하며 생성)  

이제 kmkim/ 폴더의 개인 작업 내용을 확인하고 이어서 작업할 수 있다.

6 결론

Git 브랜치는 코드 버전 관리와 협업의 핵심 도구이다. 다양한 명령어를 익히고, 상황에 맞는 브랜치 전략을 수립하여 활용하면 개발 생산성을 크게 향상시키고 안정적인 프로젝트 관리를 할 수 있다.

Subscribe

Enjoy this blog? Get notified of new posts by email: