본문으로 건너뛰기

BUMDAY · ENGINEERING NOTES

개발의 과정과
문제 해결의 기록.

직접 만들고, 부딪히고, 배운 것들을 기록합니다.

Git

Git Squash Merge를 사용하는 이유와 브랜치별 적용 방법

범데이 2026. 10. 26. 00:26

Squash merge는 작업 브랜치의 여러 커밋을 하나의 의미 있는 변경 단위로 정리할 때 사용한다. 짧게 사용하는 기능 브랜치에는 유용하지만, main과 prod처럼 계속 유지되는 브랜치 사이에서 사용하면 커밋 계보가 끊어져 다음 MR에 과거 변경이 다시 표시될 수 있다.

배경

개발 중에는 기능 하나를 완성하기까지 여러 임시 커밋이 생긴다.

feat/login
A: 로그인 화면 추가
B: 오타 수정
C: 리뷰 반영
D: 테스트 코드 수정

이 브랜치를 그대로 병합하면 A, B, C, D가 모두 대상 브랜치에 남는다. Squash merge를 사용하면 네 커밋의 최종 변경 내용을 하나의 새 커밋 S로 합쳐 대상 브랜치에 반영한다.

feature: A -- B -- C -- D
                      |
                      +-- squash --> S

중요한 점은 S가 기존 커밋을 그대로 보존한 병합 커밋이 아니라, 같은 최종 내용을 가진 새로운 커밋이라는 사실이다. 따라서 파일 내용은 같아도 기존 커밋의 SHA와 부모 관계는 대상 브랜치에 남지 않는다.

절차

1단계: 브랜치가 단기 작업용인지 판단한다

Squash 사용 여부는 커밋 개수보다 브랜치의 역할을 기준으로 판단한다.

병합 유형 권장 방식 이유
기능 브랜치 → main Squash 사용 가능 짧게 사용하고 폐기하는 브랜치이므로 작업 과정의 임시 커밋을 하나의 기능 단위로 정리하기 좋다.
버그 수정 브랜치 → main Squash 사용 가능 수정 전체를 하나의 원자적인 변경으로 만들면 추적과 revert가 단순해진다.
main → prod Squash 해제 장기간 유지되는 두 브랜치의 커밋 계보를 그대로 연결해야 다음 MR 비교가 정확하다.
release → 운영 브랜치 일반적으로 Squash 해제 이미 검증된 커밋과 배포 이력을 보존해야 한다.

2단계: 작업 브랜치의 커밋을 하나의 변경 단위로 정리한다

기능 개발 중에는 WIP, fix typo, review 반영 같은 중간 커밋이 자주 생긴다. 이 커밋들이 각각 독립적인 의미를 갖지 않는다면 squash가 적합하다.

Squash를 사용하면 다음 장점이 있다.

  • main에는 기능 하나당 의미 있는 커밋 하나가 남는다.
  • 기능 전체를 한 번에 revert하기 쉽다.
  • 코드 리뷰 결과와 최종 커밋의 범위를 맞추기 쉽다.
  • 임시 수정 과정이 장기 이력을 불필요하게 차지하지 않는다.

반대로 커밋마다 독립적인 의미가 있고 각각 빌드 가능한 상태라면 squash하지 않는 편이 좋다. 세부 커밋을 보존하면 git bisect, git blame, 부분 revert와 변경 원인 추적에 도움이 된다.

3단계: 장기 브랜치 사이에서는 이력을 보존한다

main과 prod는 병합 후 삭제되지 않고 계속 유지되는 장기 브랜치이다. 이 사이를 squash로 병합하면 prod에는 main의 원래 커밋 대신 새로운 squash 커밋만 남는다.

main: A -- M1 -- M2
prod: A ----------- S

S의 파일 내용이 M1 + M2와 같아도 Git 그래프에서 M1과 M2는 prod의 조상이 아니다. 이후 main → prod MR을 만들면 GitLab이 기존 커밋을 미반영 상태로 판단해 과거 커밋이나 변경사항을 다시 표시할 수 있다.

따라서 장기 브랜치 사이에서는 squash를 해제하고 merge commit 또는 커밋 이력을 보존하는 fast-forward 방식을 사용한다.

feature/* --(squash 가능)--> main --(squash 해제)--> prod

병합 후 아래 명령의 종료 코드가 0이면 현재 main이 prod 이력에 포함된 상태이다.

git fetch origin
git merge-base --is-ancestor origin/main origin/prod

4단계: MR 체크리스트로 실수를 방지한다

기능 MR과 배포 MR의 squash 정책을 구분한다.

확인 항목 기능 브랜치 → main main → prod
Squash commits 필요에 따라 체크 체크 해제
Source branch 삭제 병합 후 삭제 가능 main 삭제 금지
중점 검토 변경 내용과 기능 단위 대상 브랜치, 배포 범위, 이력 보존

프로젝트 설정에서 squash가 기본으로 선택되어 있다면 배포 MR 템플릿이나 리뷰 체크리스트에 Squash 해제 확인을 명시한다. GitLab에서 squash가 필수로 설정되어 있다면 장기 브랜치용 MR 정책과 충돌하므로 프로젝트 관리자가 설정을 조정해야 한다.

정리

  1. Squash는 여러 작업 커밋을 하나의 의미 있는 변경 단위로 정리하기 위한 기능이다.
  2. 짧게 사용하고 삭제하는 기능·버그 수정 브랜치에서 효과적이다.
  3. 커밋별 추적, 부분 revert, bisect가 중요하면 원래 커밋을 보존하는 편이 좋다.
  4. main → prod처럼 장기 브랜치 사이에서는 squash를 해제해 커밋 계보를 유지해야 한다.

참고

728x90
반응형