Git Squash + Rebase commit 메시지 및 히스토리 정리(SourceTree)

이우건·2024년 7월 17일

서론

팀에서 개발을 git flow 전략으로 개발을 하다보면 많은 feature 브랜치가 생기게되고 커밋 수가 많아지면 과거의 커밋 히스토리를 추적하기 어려워집니다. 따라서 저희 팀은 git squash + Rebase로 commit 히스토리를 깔끔하게 정리하자는 목표를 가지게 되었습니다.

Merge: Fast Forward Merge vs 3-way-merge

Squash + rebase를 하기에 앞서 Merge의 종류인 Fast Forward Merge와 3-way-merge에 대해 알아보겠습니다.

Fast Forward Merge

💡 Fast Forward Merge란?
브랜치 간 병합 시 현재 브랜치의 HeadCommit 과 병합하려는 브랜치의 Base Commit이 일치할 경우, 현재 브랜치의 Head Commit이 병합하려는 브랜치의 Head Commit으로 이동되는 병합 방식이다.

Head Commit과 병합하려는 브랜치의 Base Commit의 일치란?

Head Commit은 마지막 커밋, Base Commit은 브랜치를 생성할 때 Base가 됐던 브랜치의 마지막 커밋이다. 즉, 현재 브랜치의 HeadCommit 과 병합하려는 브랜치의 Base Commit이 일치한다는 것은, 현재 브랜치의 마지막 지점과 병합하려는 브랜치의 생성 지점이 동일하다는 것이다.

  • 예를들어 아래와 같이 Main 브랜치로부터 생성된 A, B 브랜치가 있다. Main 브랜치의 Head Commit은 M-C2, A 브랜치의 Head Commit은 A-C2, B 브랜치의 Head Commit은 B-C2 이고, A 브랜치와 B 브랜치 모두 Base Commit이 M-C2 이다.

  • Main 브랜치에서 A 브랜치를 병합할 경우 Main 브랜치의 Head Commit인 M-C2와 A 브랜치의 Base Commit인 M-C2가 같으므로 이 지점을 연결한 후 Main 브랜치의 Head Commit A-C2 브랜치로 이동시키는 Fast Forward 방식으로 병합된다.

Head Commit과 병합하려는 브랜치의 Base Commit의 일치하지 않으면?

  • 예를 들어 설명해보겠다. 앞서 Main 브랜치가 A 브랜치와 Fast Forward 병합한 후 Main 브랜치와 B 브랜치를 병합하려는 상황이다. 현재 Main 브랜치의 Head Commit은 A-C2, B 브랜치의 Base Commit은 B-C2로 현재 Head Commit과 병합하려는 브랜치의 Base Commit이 일치하지 않는 상황이다.

💡 이때에는 3-way-merge 방식으로 병합하게 된다. 병합한 내용은 Merge Commit 에 생성되고 아래와 같은 형태의 커밋 히스토리가 생성된다.

소스트리로 Git Squash + Rebase로 Commit 메시지 정리

먼저 다음과 같은 브랜치가 있다고 생각해보겠습니다.

현재 Head Commit은 main이고 main에서 dev 브랜치를 생성하고 dev에서 feature/test1 브랜치를 생성한 모습입니다.

여기서 feature/test1 브랜치의 commit을 squash를 통해 하나로 합치고 dev에 rebase를 통해 병합해보겠습니다.

Squash Commit

  1. feature/test1 브랜치로 checkout을 해줍니다.
  2. 본인이 squash하고 싶은 커밋의 아래 커밋에서 하위 요소 대화식 재배치를 클릭합니다.
  3. 아래와 같은 화면이 뜰 것입니다. 제일 상단에 있는 커밋이 최신 커밋입니다.
    제일 상단의 커밋을 클릭하고 이전 것과 합치기를 클릭하면 아래에 있는 커밋과 합쳐지게 됩니다.
    (feature commit3 + feature commit4)
  4. 본인이 스쿼시를 하고 싶은 커밋까지 이전 것과 합치기를 클릭해줍니다.
    (feature commit1 ~ feature commit4 까지 합침)
  5. 모두 합쳤다면 메시지 편집으로 새로운 커밋 메시지를 만들어줍니다.
    팀에서 정한 커밋 메시지 컨벤션을 따라 주세요. 저희 팀은 하위 커밋 메시지를 보존합니다.
    소스트리 히스토리에서 보기 좋게 한 칸 줄 바꿈을 해줍니다.
  6. 확인을 누르시면 다음과 같이 커밋이 합쳐진 것을 확인 할 수 있습니다.

Rebase and Merge

다음은 스쿼시한 feature/test1 브랜치의 커밋을 dev 브랜치에 rebase + Merge를 해보겠습니다.

  1. rebase하려는 브랜치에 재배치를 클릭해줍니다.
  2. 충돌이 났다면 충돌을 해결해주세요.
  3. 충돌을 해결하고 커밋을 누르면 다음과 같은 메시지가 뜰 것입니다.
    재배치 계속을 클릭하고 커밋해주세요.
  4. Rebase를 마치고 커밋을 하면 다음과 같은 그래프를 나타낼 것 입니다.
    feature/test1 브랜치는 dev의 브랜치의 내용과 Fast Forward 방식으로 합쳐진 상태입니다.
    이제 dev 브랜치에 Merge를 해보겠습니다.
  5. dev 브랜치로 checkout을 해주세요.
  6. 소스트리에서 병합을 눌러주세요.
  7. 저희 팀은 커밋 히스토리 그래프를 좀 더 직관적인 확인을 위해 Fast Forward Merge가 아닌 3-way-merge를 하기로 결정되었습니다. 아래의 버튼을 꼭 클릭해주세요.

    💡 git merge --no-ff와 같은 역할을 합니다.

  1. 다음과 같이 깔끔하게 커밋 메시지를 정리하고 Merge가 된 모습을 확인 할 수 있습니다.

주의

💡 만약 로컬 저장소의 커밋을 정리하는 것이 아닌 원격 저장소의 커밋을 정리하는 것이라면 Squash 또는 Rebase를 했을 때 pull 할 수 있는 이력들이 있을 것 입니다.
이는 원격에 있는 commit과 squash or rebase를 했을 때 커밋과 달라졌기 때문인데요.
이 때 push를 하기 위해 pull을 먼저 하게된다면 pull 했을 때의 커밋이 새로 생기게 됩니다. (fetch + merge로 인해)
만약 저희 팀 처럼 커밋 히스토리를 1개로만 하고 싶으시다면 pull & push가 아닌 강제 푸쉬를 해줘야 합니다.

강제 푸쉬 명령어
git push origin <branch명> --force

참조

https://tlatmsrud.tistory.com/155

profile
머리가 나쁘면 기록이라도 잘하자

0개의 댓글