Git Branch Linear
배경
기존에는 아무 생각 없이 Branch만들고 Merge를 진행하면서 Branch 관리에 대해서 별 다른 생각과 노력을 하지 않은 채로 개발을 진행해 왔지만 이번에는 Branch를 linear하게 관리를 하고자 한다
처음에는 그냥 rebase하고 squash하면 되는거 아니야? 가장 최신 시점에서만 merge하면 되겠네! 라고 생각을 했지만 시점을 잘못 파악해 몇 번의 문제점이 생기고 Linear하지 못하게 관리가 되게 되어 PR을 다시 올리고 Branch를 다시 만드는 과정을 몇번이나 진행하게 되었다
그리고 또 하나의 고민되었던 부분은 Github PR에서 Rebase And Merge
, Squash And Merge
를 하게 되면 Fast Forward 와 같이 계속해서 하나의 Branch 뒤에 commit내역이 쌓일 뿐 작업 완료 후에는 어떤 Branch에서 언제 Merge를 했는지 알 수가 없었고 이에 4가지 방식에 대해서 알아보았다
방식
Github PR 이용
사용 시점 : 아무래도 Fast Forward 방식으로 Merge가 이루어 지기 때문에 아무런 처리 없이 Github PR을 닫을 때는 크게 중요하지 않을 때 혹은 Commit내역이 적을 때
Rebase And Merge
Commit 내역이 적을 때
Squash And Merge
문서화 작업, 네이밍 변경 등 크게 production 환경에 영향을 주지 않을 때
3-way Merge
사용 시점 : 이 방식으로 할 경우에는 항상 조심하고 또 조심해야하는데 Commit 내역이 많고 중요한 기능을 개발할 때, 어느 Commit 부터 분기가 시작하고 종료되었는지를 나타내고 싶을 때
선 Rebase 후 PR
현재 다음과 같이 develop
Branch로부터 두개의 분기가 생겼고 feat/GM-1
Branch를 develop 가장 최신 Commit 앞으로 Rebase를 먼저 시킨 후 PR을 보내면 된다
Rebase 처리 방법
Rebase 후 상태
PR Merge 후 상태
선 PR 후 Rebase
위 방식 처럼 Rebase를 먼저 하고나서 PR을 올렸다 하더라도 협업을 하게 되면 결국 다른 팀원의 PR이 먼저 Merge되어 내가 PR을 올릴 시점보다 Merge를 시킬 Branch에 Commit이 늘어나게 되어 앞선 과정이 의미가 없게 된다
이럴 경우 다시 한번 Rebase를 해준 후 Push를 해주면 해당 PR에 다시 반영이 된다
변경 내용 PR 올린 상태에서 추가 커밋이 생성된 상황
아래 Commit Id를 잘 확인해보자
우선 또 다른 Commit들이 올라왔을 수도 있으니 한번 Rebase의 타겟이 될 Branch (여기서는 develop) 한번 최신화를 시켜주자
Rebase 처리 방법
타겟 Branch가 최신화가 되었다면 그 상태에서 Rebase 후 git push -f
를 통해서 Repository에 Rebase된 내역으로 덮어씌워주자
git push
시 에러 발생
! [rejected] feat/GM-2 -> feat/GM-2 (non-fast-forward)
error: failed to push some refs to 'https://github.com//Super-Repository.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Rebase 후 상태
Rebase가 잘 적용이 된 것을 확인 할 수 있고 이제 3-way Merge를 진행해도 Branch는 Linear하게 적용이 될 수 있게 되었다
Commit Id를 확인하면 이전과 달라진 것을 확인 할 수 있다
Commit이 많을 경우
Commit이 너무 많다면 Squash And Merge
를 고려해볼 수 있지만 Commit이 중요하고 남겨야 하는 상황에서는 한번에 뭉쳐서 올린다는 것은 좋지 않은 선택일 수도 있다
이때는 git rebase -i
를 사용해서 Commit들을 하나로 합쳐보자
아래와 같이 인사말을 추가한 4개의 Commit들이 있는데 ‘인사말 추가’라는 Commit 하나로 합쳐서 관리하는 것도 좋아보인다
Rebase interactively
다음 명령어를 통해 Commit들에 직접 상호작용하여 관리를 해보자 (bf150b93는 Commit hi이전에 있는 Merge pull
~~~에 대한 Commit Id이다)
-i 뒤에 작성항 id를 기점으로 다음 Commit들을 불러온다
여기서 pick을 squash, fixup으로 변경을 해주면 되는데 이는 squash, fixup로 작성한 Commit을 바로 이전 Commit과 하나로 합친다는 것이다
squash와 fixup의 차이로는 squash는 각 Commit들의 메시지가 합쳐지는 반면 fixup은 이전 Commit의 메시지만 남는다는 것이다
다음과 같이 hi 다음의 Commit들을 모두 squash로 변경을 해주었다
작성을 완료하고 :wq
를 통해 빠져나오면 아래와 같은 화면을 볼 수 있는데 이곳에서 Commit 메시지를 수정을 해주면 된다
처음에 많았던 Commit들을 하나로 합쳐서 관리가 되게 되었다
순서도 같이 변경 하고 싶을 때
위에서는 연속된 Commit들을 관리를 해서 크게 문제가 되진 않았지만 떨어져있는 Commit을 하나로 합치고 싶은 경우도 있을 것이다
다음과 같은 Commit들이 있고 덧셈을 한 Commit들만 합치고 싶은데 중간에 곱셈에 대한 Commit이 떡 하니 자리를 잡고있다
(짜증나네)
우선 앞서 했던 것 처럼 인사말 추가 Commit Id(e17f402c)를 가지고 rebase -i 를 시켜보자
다음과 같은 화면을 볼 수 있고 곱셈 Commit이 중간에 끼어있는 것을 순서를 아래로 내려보자
4번째 Rebase Conflict 상황
Intellij를 이용해서 Conflict가 나는 부분을 해결해 준 후 git add .
& git rebase --continue
를 사용해서 다음 5번째 Rebase 단계로 넘어가도록 하였다
5번째 Rebase Conflict 상황
이후 5번째 단계에서의 conflict까지 모두 해결을 하였고 Commit들의 순서를 변경하고 합치는 것 까지 모두 진행을 해보았다
이미 PR을 올렸을 경우
이미 위의 Commit들에 대해서 Push 후 PR을 올린 후에 Java와 Spring에 대해서 Commit을 합쳐보자
위에서 한것과 같이 git rebase -i
를 사용해서 Commit들을 하나로 합쳤고 remote와 local의 상태가 달라진 것을 볼 수 있다
이때 git push -f
를 통해서 remote의 상태를 local과 동일하게 맞춰주자
PR과 Commit 내역들 모두 하나로 합쳐진 것을 볼 수 있다
개발을 진행하면서 Commit내역까지 신경을 써야하지만 가끔 신경을 못 쓸 경우가 생기기 마련이다
히스토리 관리에 조금 더 수월하게 하기 위해 다음 방법들을 사용해서 PR을 올리기 전 Commit내역들을 정리하고 올리도록 하면 좋을 듯 하다
추가
Remote에서는 사용을 다한 Branch를 지웠고 Local에서도 반영을 하기 위해 git pull
혹은 git remote update
를 해도 Branch가 남아있는데 두 명령어는 존재하는 Branch를 가져오기만 할 뿐 사제된 것을 반영하지 않는다
Remote에서 지운 Branch를 반영하기 위해서는 git fetch --prune
혹은 git remote prune origin
을 사용해서 반영하면 된다
참고
[Git] Merge 이해하기 (Merge / Squash and Merge / Rebase and Merge)
Git Rebase Interactive로 커밋 로그 수정하기
'공부기록 > 기술공유' 카테고리의 다른 글
RequestBody Runtime시 동적 주입 (0) | 2023.11.15 |
---|---|
??? : 어딜 보시는 거죠 그건 제 잔상입니다만?!? (0) | 2023.11.13 |
Redis 사용기 (2) | 2023.11.12 |
이력서 저장 테이블 구조 재구성 (0) | 2023.11.10 |
Git Submodule 적용기 (0) | 2023.10.08 |