Dev/VCS

Git rebase, squash

dragonhyeon 2024. 12. 27. 14:21
728x90
반응형

rebase

rebase 는 브랜치의 분기 이후의 커밋들을 부모 브랜치의 최근 커밋 위로 재배치 해주는 작업입니다.

rebase 이전

 

rebase 를 진행하는 방식은 크게 두 가지가 있습니다.

 

  • 아래와 같이 실행하면 develop 브랜치의 분기 이후의 커밋들을 main 브랜치의 최근 커밋 위로 재배치 해줍니다.
git switch develop  # develop 브랜치로 이동
git rebase main     # main 브랜치로 rebase

 

  • 아래는 -i 옵션을 사용하여 리베이스 작업을 인터랙티브하게 진행하는 방식입니다. git rebase -i 명령어를 사용하면 단순히 git rebase 했을때와 다르게 리베이스 과정 중에 커밋을 수정, 삭제, 합치기 등 세부적으로 제어할 수 있습니다.
git switch develop  # develop 브랜치로 이동
git rebase -i main  # main 브랜치로 인터랙티브하게 rebase
리베이스 편집기에서 명령어 오타, 혹은 논리적 오류 등으로 인해 작업 설정에 오류가 발생했을 경우 경우 git rebase --edit-todo 를 통해 리베이스 편집기를 다시 열어 리베이스 todo 리스트를 다시 수정한 후 편집기를 닫고 git rebase --continue 를 입력해주면 다음 단계로 정상적으로 넘어갑니다.

 

rebase 진행중에 리베이스 충돌이 발생하면 (pick, squash 모두) 그때마다 충돌을 해결하고 수정 파일을 스테이징 영역에 추가한 후 git rebase --continue 를 입력해주면 커밋 메시지를 수정할 수 있는 편집창이 나타나며 (pick 의 경우 하나의 커밋에 대해, squash 의 경우 여러 커밋을 합친 커밋에 대해) 커밋 메시지 작성 후 다음 작업으로 넘어갑니다.

git add <conflicted-files>  # 리베이스 충돌 파일 수정 후 스테이징 영역에 추가
git rebase --continue       # 리베이스 재개

 

리베이스 충돌이 발생하지 않았을 경우 pick 의 경우 커밋 메시지 수정 없이 바로 다음 작업으로 넘어가며, squash 의 경우 연달아 나오는 squash 의 마지막 커밋까지 합친 커밋의 커밋 메시지를 작성하는 편집창이 나타납니다.

 

rebase 가 완료되면 아래와 같이 분기된 브랜치의 분기 이후의 커밋들이 부모 브랜치의 최근 커밋 위로 재배치되어 커밋 히스토리가 선형적으로 이어집니다.

rebase 완료

squash

브랜치 squash 는 브랜치 내 여러 개의 커밋을 하나의 커밋으로 압축하는 작업입니다. 이는 PR 을 올릴때 깔끔한 히스토리를 유지할 수 있게 도와줍니다. git rebase 를 통해 squash 를 진행할 수 있으며 그 과정은 다음과 같습니다.

 

1. 압축하고자하는 브랜치에서 git rebase -i 명령어를 사용하여 인터랙티브 리베이스 모드에 진입합니다.

git switch develop    # develop 브랜치로 이동
git rebase -i HEAD~6  # 가장 최근 커밋 여섯 개에 대해 squash 관련 설정 지정

 

2. 리베이스 편집기에서 squash 할 커밋을 선택합니다. pick 을 사용하면 해당 커밋을 그대로 유지하며 squash 를 사용하면 해당 커밋을 이전 커밋과 합칩니다. 아래 예시의 경우 ghi9012def5678 로, mno7890, pqr1234jkl3456 으로 squash 됩니다.

pick abc1234 First commit
pick def5678 Second commit
squash ghi9012 Third commit
pick jkl3456 Fourth commit
squash mno7890 Fifth commit
squash pqr1234 Sixth commit
가장 맨 위의 커밋이 가장 과거의 커밋이며 아래로 갈수록 최근 커밋입니다.

 

3. squash 작업 설정을 완료하면 Git 은 새로운 커밋 메시지를 작성할 수 있는 편집기를 열어줍니다. 이 곳에서 새로운 커밋 메시지를 작성하거나, 기존 커밋 메시지를 조합하여 자유롭게 편집할 수 있습니다. 위의 예시와 같이 커밋이 압축되는 지점이 두 군데라면 커밋 메시지 또한 두 번 작성하게 됩니다.

git merge --squash

브랜치 병합시 --squash 옵션을 사용하면 대상 브랜치의 커밋을 하나의 커밋으로 압축하여 병합을 진행할 수 있습니다.

squash 이전

git switch main             # main 브랜치로 이동
git merge --squash develop  # develop 브랜치 squash 하여 병합

 

병합 충돌이 발생했을 경우 기존 병합 충돌 처리 방식과 동일하게 병합 충돌이 발생한 파일을 수정한 후 수정 파일을 스테이징 영역으로 이동한 뒤 커밋을 진행하면 됩니다.

 

병합 충돌이 발생하지 않았을 경우 git merge --squash 는 병합 커밋과 구분되는 동작을 의도한 설계 원칙 때문에 자동으로 커밋을 생성하지 않습니다. 따라서 다음과 같이 직접 커밋을 진행해주어야 병합이 완료됩니다.

git commit  # 커밋 진행 (자동 생성 커밋 메시지 사용 혹은 수정)

 

squash 를 통해 병합을 진행하면 아래와 같이 병합 커밋은 생성되지 않습니다. 즉, 병합 기록이 남지 않고 하나의 커밋이 선형적으로 이어집니다.

squash 완료

 

이 작업은 git rebase -i 를 통해서도 동일하게 수행할 수 있습니다.

git switch develop  # develop 브랜치로 이동
git rebase -i main  # 가장 과거의 커밋만 pick, 나머지 커밋은 모두 squash
git switch main     # main 브랜치로 이동
git merge develop   # develop 브랜치와 병합
두 접근 방식 모두 main 브랜치에 하나의 커밋으로 병합되며, 결과는 동일하지만 과정에서의 차이가 발생합니다. git merge --squash develop 은 develop 브랜치를 그대로 유지하지만 git rebase -i develop 은 develop 브랜치의 히스토리를 정리하는 과정이 포함됩니다.
728x90
반응형

'Dev > VCS' 카테고리의 다른 글

Git 태그  (2) 2024.12.31
Git 브랜치 삭제  (3) 2024.12.29
Git fast-forward merge, 3-way merge  (0) 2024.12.24
Git 협업 방법 clone, fork  (2) 2024.12.17
Git 원격 브랜치, 원격 추적 브랜치, 트래킹 브랜치  (4) 2024.12.17