병합(Merge) — merge의 작동 방식과 병합 전략

저자: IT Sectr 게시일: 2026-08-01 읽는 시간: 9 분

병합(Merge)은 Git에서 두 개의 다른 개발 라인에서 변경 사항을 하나의 대상 브랜치로 결합하는 브랜치 병합 작업입니다. rebase와 달리 merge는 두 개의 부모를 가진 특별한 병합 커밋을 생성하여 전체 분기 기록을 보존합니다. Git 공식 문서(2026)에 따르면, merge는 기록을 덮어쓰지 않고 언제 어떤 브랜치가 병합되었는지 추적할 수 있기 때문에 브랜치를 결합하는 가장 안전한 방법입니다. main, develop, release와 같은 공개 브랜치에서 병합을 위한 표준 선택입니다.

핵심 포인트

  • 병합(Merge) — 두 브랜치의 기록을 보존하는 병합 커밋을 생성하여 브랜치를 결합.
  • 병합 커밋 — 병합 이벤트를 기록하는 두 개의 부모를 가진 특별한 커밋.
  • 병합 전략 — recursive, octopus, ours, squash — 각각 다른 시나리오에 적합.
  • 충돌 — 두 브랜치에서 동일한 줄이 변경될 때 발생하며 수동 해결 필요.
  • 안전성 — merge는 기존 커밋을 수정하지 않으므로 공개 브랜치에 안전.

Git에서 병합이란

병합(Merge)은 지정된 브랜치의 변경 사항을 현재 브랜치로 결합하는 git merge 명령어입니다. Git은 공통 조상(베이스 커밋)을 찾고, 조상을 기준으로 각 브랜치의 diff를 계산한 후, 결합된 변경 사항 세트를 포함하는 병합 커밋을 생성합니다. 결과적으로 대상 브랜치는 병합된 브랜치의 모든 변경 사항을 받습니다.

구문: 대상 브랜치(예: main)에 있는 상태에서 git merge feature를 실행합니다. 충돌이 없으면 Git이 자동으로 병합 커밋을 생성합니다. 기본 병합 커밋 메시지는 “Merge branch 'feature' into main”입니다. -m 플래그를 사용하여 메시지를 변경하거나 열린 편집기에서 편집할 수 있습니다.

병합은 비파괴적 작업입니다. rebase와 달리 merge는 기존 커밋을 건드리지 않습니다. 커밋은 동일한 해시, 작성자 및 날짜를 유지합니다. 이로 인해 merge는 여러 개발자가 동시에 작업하는 브랜치를 병합하는 유일한 안전한 방법입니다. 문제가 발생하면 git merge --abort로 병합을 취소할 수 있습니다.

bash
# 대상 브랜치로 전환
git checkout main

# 기능 브랜치 병합
git merge feature

# 결과 — 두 부모가 있는 병합 커밋
git log --oneline --graph

# 사용자 정의 메시지로 병합
git merge feature -m "feat: integrate authentication module"

병합 유형: regular, squash, fast-forward

Git은 원하는 결과에 따라 선택되는 세 가지 병합 모드를 지원합니다. 일반 병합(기본값)은 병합 커밋을 생성합니다. Squash 병합은 기능 브랜치의 모든 커밋을 하나로 결합합니다. Fast-forward는 가능한 경우 커밋을 생성하지 않고 브랜치 포인터를 앞으로 이동합니다. 모드 선택은 팀의 워크플로와 기록 규칙에 따라 달라집니다.

일반 병합(--no-ff) — fast-forward로 수행할 수 있는 경우에도 병합 커밋을 생성합니다. main 브랜치에 권장됩니다. 병합 커밋은 기능 통합 지점을 명확하게 표시하고 단일 병합 커밋 되돌리기로 기능 브랜치의 모든 변경 사항을 쉽게 되돌릴 수 있습니다. GitHub는 PR을 Merge 버튼으로 병합할 때 기본적으로 이 모드를 사용합니다.

Squash 병합(--squash) — 기능 브랜치의 모든 커밋을 대상 브랜치의 단일 커밋으로 수집합니다. 기능 브랜치의 초안 기록이 main을 오염시키지 않아야 할 때 유용합니다. 단점: 원본 커밋과의 연결이 끊어져 기능이 단계별로 어떻게 개발되었는지 볼 수 없습니다. GitHub는 PR에서 “Squash and merge”를 선택할 때 이 모드를 사용합니다.

Fast-forward(--ff) — 기능 브랜치가 분기된 이후 대상 브랜치에 새 커밋이 없으면 Git은 병합 커밋을 생성하지 않고 포인터를 앞으로 이동합니다. 기록은 선형을 유지합니다. --no-ff 플래그는 병합 커밋을 강제하고, --ff-only는 fast-forward가 불가능한 경우 오류를 발생시킵니다.

bash
# 병합 커밋 강제(main에 권장)
git merge --no-ff feature

# Squash 병합 — 모든 커밋을 하나로
git merge --squash feature
git commit -m "feat: add authentication"

# Fast-forward만 가능한 경우
git merge --ff-only feature

# 충돌 병합 중단
git merge --abort

Git 병합 전략

병합 전략은 Git이 변경 사항을 결합하는 데 사용하는 알고리즘을 결정합니다. 각 전략은 다양한 시나리오에 적합합니다. Git은 자동으로 적절한 전략을 선택하지만 개발자는 --strategy 플래그를 사용하여 명시적으로 지정할 수 있습니다. 전략을 이해하면 복잡한 병합에서 Git의 동작을 예측하는 데 도움이 됩니다.

Recursive — 두 브랜치를 병합하기 위한 기본 전략. Git은 공통 조상을 찾고, 각 브랜치의 변경 사항을 계산한 후 병합합니다. 공통 조상이 발견되면 recursive는 파일 이름 변경 및 추가를 올바르게 처리합니다. 충돌 시 recursive는 추가 옵션을 사용할 수 있습니다: ours(자동으로 우리 버전 선택)와 theirs(상대방 버전 선택).

Octopus — 두 개 이상의 브랜치를 동시에 병합하는 경우: git merge feature1 feature2 feature3. Octopus는 충돌 해결을 지원하지 않습니다 — 명령어를 호출하기 전에 모든 충돌을 해결해야 합니다. 주로 충돌하지 않는 것이 보장된 여러 독립적인 브랜치(예: 다른 모듈)를 병합하는 데 드물게 사용됩니다.

전략브랜치 수충돌 해결
Recursive2자동 + ours/theirs 옵션
Octopus3+없음 — 모든 충돌을 미리 해결해야 함
Ours모든항상 우리 버전 선택, 상대방 변경 무시
Subtree2서브트리 병합용

Ours — 병합된 브랜치의 변경 사항을 완전히 무시하고 대상 브랜치의 현재 내용을 유지하는 특별한 전략입니다. 병합 커밋은 생성되지만 내용은 변경되지 않습니다. 기록에 병합 사실을 기록해야 하지만 실제로는 다른 브랜치의 모든 변경 사항을 거부하려는 경우에 유용합니다.

병합 충돌 해결

병합 충돌은 파일의 동일한 줄이 두 브랜치에서 다르게 변경될 때 발생합니다. Git은 어느 버전이 올바른지 자동으로 판단할 수 없으며 병합을 중단합니다. 충돌은 한 브랜치에서 파일 이름이 변경되고 다른 브랜치에서 수정되거나, 동일한 파일이 동시에 삭제 및 수정될 때도 발생할 수 있습니다.

해결 과정: Git은 충돌하는 파일에 표시자를 표시합니다. 파일에는 <<<<<<< HEAD(우리 버전), =======(구분자), >>>>>>> feature(상대방 버전) 섹션이 표시됩니다. 개발자는 충돌 섹션을 수동으로 편집하고, 두 버전에서 원하는 줄을 선택하고, 표시자를 제거하고, 파일을 저장한 후 git add로 인덱스에 추가합니다.

시각적 충돌 해결을 위해 Git은 mergetool을 지원합니다 — 외부 비교 도구입니다. 인기 있는 mergetool: Meld, KDiff3, Beyond Compare, VS Code(내장 충돌 편집기). Mergetool은 세 개의 패널(우리 버전, 상대방 버전, 결과)을 표시합니다. 개발자는 최종 파일에 포함할 코드 블록을 시각적으로 선택합니다.

bash
# 병합 시작 및 충돌 감지
git merge feature
# 충돌(내용): src/main.swift에서 병합 충돌

# 충돌 파일 확인
git status

# 시각적 mergetool 열기
git mergetool

# 해결 후 — add 및 commit
git add src/main.swift
git commit

# 병합 중단
git merge --abort

rebase 대신 merge를 선택해야 하는 경우

Merge가 rebase보다 선호됩니다 몇 가지 주요 상황에서. 첫째: 다른 개발자가 접근할 수 있는 공개 브랜치로 작업할 때. Merge는 기록을 덮어쓰지 않으므로 동료가 안전하게 동기화할 수 있습니다. 공개 브랜치에서 rebase를 수행하면 분기된 기록이 생성되고 이미 이전 커밋을 가진 모든 사람에게 충돌이 발생합니다.

두 번째 상황: 기능 브랜치를 완료할 때. 대부분의 팀은 기능 통합 시점을 기록하기 위해 main에 대한 merge(--no-ff 플래그 사용)를 선호합니다. 이렇게 하면 기록 탐색이 간소화되고 병합 커밋을 한 번 git revert하는 것만으로 전체 기능을 쉽게 되돌릴 수 있습니다. GitHub Flow는 기본적으로 세 가지 병합 옵션을 제공합니다: 단순 병합, squash 병합, rebase 병합.

세 번째 상황: 검토된 풀 리퀘스트로 작업할 때. GitHub와 GitLab은 다양한 옵션이 있는 병합 버튼을 제공합니다. Merge(Create a merge commit) — 병합 커밋이 있는 전체 기록. Squash and merge — 개발 세부 사항이 없는 깔끔한 기록. Rebase and merge — 병합 커밋 없이 선형 기록이지만 커밋 재작성 포함. 선택은 팀 규칙에 따라 다릅니다.

  • 공개 브랜치(main, develop) — merge만, 절대 rebase 안 함.
  • PR 완료 — 통합 지점 표시를 위해 --no-ff로 merge.
  • 타인의 커밋이 있는 브랜치 — merge는 타인의 작업을 덮어쓰지 않음.
  • 릴리스 전 — merge가 위험이 적어 더 안전함.
  • 공유 브랜치 — 여러 개발자가 브랜치에서 작업하면 merge가 필수.

브랜치 병합 모범 사례

첫 번째 규칙: 병합 전에 항상 대상 브랜치의 최신 버전을 사용합니다. 기능 브랜치를 병합하기 전에 git checkout main && git pull을 실행합니다. 이렇게 하면 충돌이 최소화되고 병합 커밋에 모든 최신 변경 사항이 포함됩니다. 대상 브랜치가 크게 앞서 있는 경우 먼저 기능 브랜치 내에서 git merge main을 실행하여 해당 컨텍스트에서 충돌을 해결합니다.

두 번째 규칙: 병합 후 코드를 테스트합니다. 충돌이 없더라도 병합으로 인해 동작이 변경될 수 있습니다. CI/CD 파이프라인은 프로덕션으로 보내기 전에 병합 커밋에서 테스트를 실행해야 합니다. 일부 팀은 병합 게이트를 사용합니다 — 통과할 때까지 병합을 차단하는 필수 검사입니다.

세 번째 규칙: 병합 커밋을 문서화합니다. 기본 메시지 “Merge branch 'feature' into main”은 별로 유용하지 않습니다. 무엇이 병합되었는지 설명을 추가하는 것이 좋습니다: “Merge authentication module: login, registration, password recovery”. 이렇게 하면 기록 분석과 회귀 검색이 쉬워집니다. 대규모 프로젝트에서는 병합 커밋이 PR 제목에서 자동 생성됩니다.

  • 최신 상태 — 병합 전에 대상 브랜치가 업데이트되었는지 확인(git pull).
  • 테스트 — CI/CD는 결과 병합 커밋에서 테스트를 실행해야 함.
  • 설명 메시지 — 병합 커밋에 어떤 기능이 병합되었는지 명시.
  • 빈도 — 기능 브랜치를 가능한 한 빠르고 자주 병합(최대 1주일).
  • 되돌리기 — 병합 커밋의 git revert로 전체 기능을 롤백.

자주 묻는 질문

Git에서 브랜치를 병합한다는 것은 무엇을 의미하나요?

병합한다는 것은 한 브랜치에서 다른 브랜치로 변경 사항을 결합하기 위해 git merge를 실행하는 것을 의미합니다. 결과는 병합 이벤트를 기록하고 두 브랜치의 변경 사항을 포함하는 병합 커밋입니다. 이것이 Git Flow에서 기능 브랜치를 main, develop 또는 release에 통합하는 기본 방법입니다.

Squash 병합과 일반 병합의 차이점은 무엇인가요?

Squash 병합은 기능 브랜치의 모든 커밋을 대상 브랜치의 단일 커밋으로 결합하여 중간 개발 기록을 잃습니다. 일반 병합은 모든 기능 브랜치 커밋을 보존하면서 병합 커밋을 생성합니다. Squash 병합은 깔끔한 기록을 제공하지만 기능의 단계별 개발을 추적할 수 없습니다.

Git에서 병합 충돌을 해결하려면 어떻게 해야 하나요?

충돌하는 파일을 열고 <<<<<<< HEAD>>>>>>> 표시자가 있는 섹션을 찾습니다. 내용을 편집하고 두 버전에서 필요한 줄을 유지한 후 표시자를 제거합니다. 파일을 저장하고 git add와 git commit을 실행합니다. 시각적 해결을 위해 git mergetool을 사용할 수 있습니다.

rebase 대신 merge를 사용해야 하는 경우는?

Merge는 항상 공개 브랜치(main, develop, release)에 사용됩니다. 기록을 덮어쓰지 않기 때문입니다. Rebase는 게시 전 개인 기능 브랜치에 적용됩니다. 브랜치가 공유 저장소의 일부가 되고 동료가 접근한 후에는 merge만 허용됩니다.

Git에서 병합을 어떻게 취소하나요?

병합 완료 전(충돌 중) — git merge --abort로 병합을 완전히 취소합니다. 완료 후 — git revert <merge-commit-hash> -m 1로 되돌리기 커밋을 생성합니다. -m 1 플래그는 유지할 부모 브랜치(대상)를 지정합니다. 게시된 브랜치의 경우 git revert가 git reset보다 안전합니다.

요약

  • 병합(Merge) — 기록을 보존하고 두 부모가 있는 병합 커밋을 생성하는 안전한 브랜치 결합.
  • 병합 모드 — 일반(--no-ff), squash(--squash), fast-forward(--ff).
  • 전략 — recursive(기본), octopus(3+ 브랜치), ours(상대방 변경 무시).
  • 충돌 — 표시된 섹션을 편집하거나 mergetool을 사용하여 수동 해결.
  • 안전성 — merge는 기존 커밋을 수정하지 않아 공개 브랜치에 안전.
  • Squash 병합 — 모든 커밋을 하나로 결합, 중간 개발 기록 손실.
  • 병합 되돌리기 — 게시된 변경 사항의 안전한 롤백을 위해 -m 1 플래그로 병합 커밋 git revert.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기