[GitHub] Squash and Merge를 선택한 이유

낙경·2024년 4월 12일

코끼리 개발 일지

목록 보기
3/7

상황 및 문제

기존 프로젝트에는 three-wayfast-forward 상관 없이 git flow를 따르며 merge하는 행위 자체에 의의를 뒀었다.

하지만 이슈가 쌓이고, 그래프들이 많이 merge될 수록
git graph가 몹시 지저분해져 보기 싫었다.

[ 극단적인 예시 ]


원인

git flow를 지키는 것까지는 좋았지만

  1. --no-ff에 의해 merge commit이 생성되며 그래프가 못생기게 합쳐짐
  2. squash를 사용하지 않음

두가지 문제가 있었다.

merge 옵션

git에서 제공하는 merge 옵션은 세가지가 있다

  1. --ff
  2. --no-ff
  3. --squash

하나씩 간단히 알아보자.

1. --ff

fast-forward

만약 현재 브랜치랑 머지 대상 브랜치가 fast-forward 관계에 놓인 경우에 새로운 commit을 생성하는 대신 브랜치 참조 값만 변경되도록 함
아니라면 merge commit 생성

2. --no-ff

non fast-forward

fast-forward 관계여도 강제로 merge commit을 생성하고 병합함

  • 브랜치 관계에 상관없이 필요한 commit 만 가져올 수 있음
  • 어떤 브랜치에서 merge를 했는지 기록을 남길 수 있음
    Merge branch 'dev1'

3. --squash

squash: 짓뭉개다

commit이력과 merge된 브랜치 이력을 남기지 않음
새로운 commit에 상대 브랜치의 내용을 모두 뭉쳐 놓음

  • 단, commit이 자동으로 생성되지 않고 뭉쳐진 내용이 stage에 올라오므로 이를 commit 해야함


GITHUB에서 제공하는 merge 옵션

그와 별도로 github에서 제공하는 merge 옵션은 다음과 같다

1. Create a merge commit

--no-ff 방식으로 커밋이 이루어짐
가장 기본적인 방식
별도로 알아보지 않았다면, 항상 이 방식으로 pr을 머지했을 가능성이 농후함

  • 병합 대상 브랜치에 병합 요청 브랜치의 커밋을 모두 달고옴
  • 추가로 두 브랜치에대한 새로운 머지 커밋을 생성하기 때문에, 연결 선이 생김
  • 이 연결 선이 많아지면 복잡해 보임
  • 하지만 커밋 병합 과정이 시각적으로 명확하게 보임

2. Squash and merge

--squash를 사용할 것 같지만 그렇지 않음, github 자체에서 제공하는 별도의 merge 방법

  • 병합을 요청하는 브랜치의 모든 커밋을 하나의 커밋으로 압축함
  • 병합 대상 브랜치의 현재 헤드 다음에 압축한 커밋을 추가
  • fast-forward 방식으로 해당 커밋을 병합 대상 브랜치에 merge 함
  • 이 과정에서 병합을 요청하는 브랜치의 커밋은 따라오지 않으므로 브랜치 삭제시 해당 커밋들은 추적할 수 없게 됨
  • 하지만 브랜치를 깔끔하게 유지할 수 있음

3. Rebase and merge

git의 rebase 기능을 사용함

  • 병합을 요청하는 브랜치와, 병합 대상 브랜치의 공통 조상을 찾음
  • 병합을 요청하는 브랜치의 공통 조상 이후 커밋들을 병합 대상 브랜치 위에 하나씩 새로 추가
  • 하지만 만약 conflict가 발생할 것이 확인된다면 github에서 Rebase and merge 불가
  • 로컬에서 직접 rebase 시도 후 force-push 하여 새 커밋들을 덮어써야함
  • 그 후 github에서 다시 merge 시도



해결

결론은 우리는 Squash and merge 방식을 사용하기로 결정했다

우선 Create a merge commit의 대안을 찾기 위한 시도였기 때문에, 첫번째 방법은 건너뛰고,
Rebase and merge 방식의 경우, 우리 팀의 규칙 자체에 PR 전 최신 develop 브랜치에 rebase하기가 존재하기 때문에 의미가 없었다.

또한 깃 그래프를 깔끔하게 유지하는 것이 우리 팀의 목표였기 때문에, PR에 올라간 커밋들을 모두 하나의 커밋으로 압축하여 develop 브랜치에 추가하는 부분이 아주 만족스러웠다.

병합을 요청하는 브랜치의 커밋은 따라오지 않으므로 브랜치 삭제시 해당 커밋들은 추적할 수 없게 된다는 단점은, 삭제한 브랜치 혹은 PR이 완료된 브랜치는 삭제 후 다시 사용하지 않는 우리 팀에게는 큰 단점이 되지 않았다.

그리고 추적은 되지 않지만, Github에서 편의를 제공해줘 merge 시점에 commit 제목과, 상세 내용을 기본적으로 제공하는 것이 마음에 들었다. 특히 상세 내용에 해당 브랜치에서 했던 커밋들의 제목이 모두 올라오기 때문에, 커밋 내용을 하나하나 추적할 수는 없어도 대략적인 내용을 알 수 있었다.

깔끔해진 그래프

squash로 연결 선 없이 기존 브랜치는 그대로 남아 이쁜 일직선 유지

develop 브랜치 자체도 커밋 네이밍 규칙이 통일되어 보기 좋음

만약 squash and merge만 허용하고 싶다면?

settings에서 Pull Request에 대한 내용을 설정할 수 있다.
이 곳에서 Allow squash merging만 체크하면 된다.


참고

https://wikidocs.net/153871
About pull request merges

0개의 댓글