학습 배경
이직한 회사에서 rebase and merge라는 방식의 merge 방법을 채택하고 있었는데 나에겐 rebase and merge라는 개념이 생소하여 학습하게 되었다.
Merge
일반적으로 많이 사용되는 병합이며, 커밋 이력을 모두 남길 때 사용한다.
서로 다른 브랜치에서 작업을 했거나, 작업 내용을 합쳐야 하는 경우 merge를 해주면 됨
브랜치 상태 확인
Checkout한 브랜치를 기준으로 —merged, —no-merged 옵션을 사용하여 merge가 된 브랜치인지 아닌지 필터링할 수 있다.
git branch --merged
git branch --no-merged
Merge 하기
‘현재' 브랜치에서 [브랜치 명]의 변경사항을 병합
예를 들어 master브랜치와 test 브랜치가 있다고 했을 경우,
**git merge test**를 하게되면
test브랜치에만 있던 코드가 master브랜치에 병합된다.
// master에 체크아웃
git checkout master
// test브랜치의 코드를 master에 합침
git merge test
git merge [브랜치명]
Merge시 충돌 해결하기
1) merge conflict
- merge할 때 발생하는 conflict(충돌)
- 에러를 안내느냐가 아닌 해결할 수 있느냐가 중요함
2) 충돌이 생길 경우
- git은 충돌 내용을 하단과 같이 코드 상에 보여준다.
&&<<<<<<< HEAD
{현재 브랜치의 다른 파일 내용}
=======
{충돌나는 브랜치명 또는 commit에서의 다른 파일 내용}
>>>>>>> 충돌나는 브랜치명 또는 commmit 아이디
- 예시
<<<<<<< HEAD
master content -> 현재 브랜치[master]에서 수정된 내용
=======
test content -> 머지할 브랜치[test]에서 수정한 내용
>>>>>>> 충돌나는 브랜치명 또는 commmit 아이디
서로 다른 부분을 수정해줘야 함.
3) 충돌 안 나도록 하는 명령어
# 대상 브랜치로 이동
git checkout [대상브랜치]
# 대상 브런치의 로컬 최신화
git pull origin [대상브랜치]
# 다시 내 작업 브랜치로 이동
git checkout {작업 브랜치}
# 머지 요청
git merge [대상브랜치]
# 수정 후, add, commit, push 진행
Merge 후 브랜치 삭제
merge가 완료되었다면 사용하지 않는 브랜치를 삭제해준다.
git branch -d <branch 이름>
이 방식은 다시 Fast-Forward 방식과 Recursive 방식으로 나뉜다.
Merge (Fast-Forward)
새로운 브랜치 my-branch 가 main 브랜치로부터 분기된 이후 main 브랜치에 새로운 커밋이 올라오지 않았다면, my-
branch 가 main 와 비교하여 최신의 브랜치라고 할 수 있다. 이런 경우 my-branch 의 변경 이력을 그대로 main 으로 가져올 수 있
는데, 이를 Fast-Forward Merge 라고 한다.
Merge (Recursive)
my-branch 가 main 브랜치에서 분기되고, main 브랜치에 새로운 커밋이 생겼다면, my-branch 를 최신이라고 간주할 수 없다.
따라서 my-branch 와 main 을 공통 부모로 한 새로운 Merge Commit 을 생성하게된다. 이런 방법을 Recursive Merge라고 한다.
Fast-Forward Merge가 가능한 상태에서 git merge 명령에 --no-ff 옵션을 주면 강제로 Merge Commit을 생성하게 할 수 있다.
Squash & Merge
Squash & Merge
Squash는 여러개의 커밋을 하나의 커밋으로 합치는 것을 의미한다. Squash Merge는 병합할 브랜치의 모든 커밋을 하나의 커밋으
로 Squash한 새로운 커밋을 Base 브랜치에 추가하는 방식으로 병합하는 것을 의미한다.
Squash를 하게 되면 모든 커밋 이력이 하나의 커밋으로 합쳐지며 사라진다는 점을 주의해야한다.
$ git checkout main $ git merge --squash my-branch $ git commit -m "squash & merge"
Rebase & Merge
Rebase를 알아보기 전에 Base가 무엇인지 알아보자. my-branch 가 main 브랜치의 A 커밋에서 분기되었다고 하자. 이때, my-branch 의 Base는 A 커밋이다.
그렇다면, Rebase는 무엇일까? 말 그대로 Base를 다시 설정한다는 의미이다. 그럼 Base를 어디로 다시 설정할까? my-branch 가
분기된 main 브랜치의 최신 커밋이다.
Rebase를 하면 커밋들의 Base가 변경되므로 Commit Hash 또한 변경 될 수 있다. 이로 인해 Force Push를 해야할 경우도 있으니
주의하자.
$ git checkout my-branch $ git rebase main $ git checkout main $ git merge my-branch
명령 순서를 보면 알겠지만, 결과적으로 Fast-Forward Merge를 사용하는 것을 확인할 수 있다.
언제 어떤 방식을 사용해야하는가?
아래 내용은 NHN Cloud Meetup!의 GitHub의 Merge, Squash and Merge, Rebase and Merge 정확히 이해하기
를 참고하여 나의 생각을 덧붙여 작성하였다.
feature → develop 머지
Squash & Merge가 유용하다. feature 브랜치에서 기능을 개발하기 위한 지저분한 커밋 내역을 하나의 커밋으로 묶어 develop 에
병합하면서, develop에는 기능 단위로 커밋이 추가되도록 정리할 수 있다.
또한 feature 브랜치는 develop 브랜치에 병합 후 제거하므로, Merge Commit 을 남길 필요가 없다.
develop → main 머지
main 브랜치는 지금까지 작업한 모든 기능을 배포할 때 병합한다. develop 브랜치를 squash & merge 하게 되면 커밋 이력이 모두
사라져, 특정 기능에서 문제가 생겼을 때 롤백할 수 없게된다. main 브랜치 또한 Merge Commit 을 남길 필요 없다. 따라서 Rebase
& Merge 가 적합하다.
Merge 전략들 비교
Merge Strategy | Pros | Cons |
Merge Commit | 아직 찾지 못함 | 불필요한 commit message가 생기고 merge 순서와 commit 순서가 별도로 기록되어 history 관리가 어려움. |
Spauash & Merge | Commit 단위 별로 꼼꼼하게 관리하지 않아도 PR title만 제대로 관리하면 history가 깔끔하게 정리됨. | Atomic level의 rollback이 어려움. |
Rebase & Merge | Atomic level의 rollback이 용이하며 commit단위의 history 기록이 됨 |
Commit을 잘 다루지 못하는 경우, rebase에 익숙하지 않은 경우 어려움이 발생. |
이제 막 git으로 버전관리하는 방법을 배우기 시작했다면 Squash and Merge가 적절한 선택으로 생각된다.
참고
'프로그래밍(Web) > 업무관련' 카테고리의 다른 글
[바미] 회귀 분석 (2) | 2024.11.19 |
---|---|
[바미] 선형 보간법 (0) | 2024.06.08 |
OpenVPN Options error: --up script fails with './update-resolv-conf': 지정된 파일을 찾을 수 없습니다. (errno=2) 해결방법 (0) | 2023.10.11 |
VisualVM 실행 시 Cannot find java 1.8 or higher 에러 뜰 때 (0) | 2023.07.13 |
Eclipse Memory Analyzer를 사용하여 메모리 누수 파악하기. (0) | 2023.06.15 |