헷갈리는 머지들
브랜치 병합을 명확하게 정리해주는 글을 잘 못 봤습니다. 그러다가 아래글을 보고 아 이거구나 싶었는데, 따라하다가 git conflict가 발생합니다. 그래서 다시 정리해봅니다.
Merge 옵션 비교
이 글은 5 branch Gitflow 를 전제하고 있습니다. (혹은 main, develop, feature 3 branch도 포함)
Github의 Merge 옵션을 다시 설명해 봅니다. (with Graph)
--- title: Situation --- flowchart LR root A1 A2 A3 B1 root --> A1 --> A2 --> A3 A3 ~~~ B1 root --> B1
Mermaid
복사
위 그림과 같은 상황이 있습니다.
--- title: Merge A into B --- flowchart LR root A1 A2 A3 B1 root --> A1 --> A2 --> A3 A3 ~~~ B1 root --> B1 A3 & B1 --> MergeCommit
Mermaid
복사
merge: 일반적인 머지 입니다. 같은 베이스로부터 시작된 A, B 의 변경사항에 충돌이 없을 경우, 새로운 커밋을 만들고 둘을 합칩니다. ( 충돌이 있을 경우, 해결하는 내용이 병합 커밋에 들어갑니다.)
--- title: Rebase ane Merge (A onto B) --- flowchart LR root A1 A2 A3 B1 A1 --> A2 --> A3 A3 ~~~ B1 root --> B1 B1 --> A1
Mermaid
복사
rebase and merge: 같은 베이스로부터 시작된 A, B 의 변경사항이 있고, A를 B에 머지할 경우, 베이스-B-A 순으로 커밋을 선형으로 만듭니다.
--- title: Squash and Merge --- flowchart LR root --> C1["Merge Commit"]
Mermaid
복사
squash and merge: 같은 베이스로부터 시작된 A, B 의 변경사항이 있고, B를 A에 머지할 경우 squah 가 먼저 되는것 같지만, merge가 되면서 squash가 됩니다. 따라서 A, B 커밋들에서 merge 충돌나면, 진행이 안됩니다. rebase를 한 뒤에 진행을 해줘야 충돌이 안납니다.
제가 혼동 하던 부분은 develop 브랜치에, feature 브랜치를 squash and merge 를 진행 할 때 였습니다. 저는 develop에 반영된 변경 사항들 다음으로 feature 브랜치가 합쳐진다고 생각했는데, 실제로는 develop과 feature를 합쳐서 커밋을 하는 것이었습니다.
Branch 별 Merge 옵션
1.
main
•
→ None
2.
feature (from develop)
•
→ develop:
◦
squash and merge( rebase 선행후) : 커밋 간소화
◦
rebase and merge: 커밋 그래프 유지
3.
sub feature
•
→ feature:
◦
squash and merge( rebase 선행후) : 커밋 간소화
◦
rebase and merge: 커밋 그래프 유지
4.
release (from develop)
•
→ main:
◦
merge : 병합 브랜치 가시화
◦
squash and merge ( rebase 선행 필요) : 커밋 간소화
◦
rebase and merge : 커밋 그래프 유지
•
→ develop:
◦
merge : 병합 브랜치 가시화
◦
squash and merge ( rebase 선행 필요) : 커밋 간소화
◦
rebase and merge : 커밋 그래프 유지
5.
hotfix (from main)
•
→ main:
◦
merge : 병합 브랜치 가시화
◦
squash and merge ( rebase 선행 필요) : 커밋 간소화
◦
rebase and merge : 커밋 그래프 유지
•
→ develop:
◦
merge : 병합 브랜치 가시화
◦
squash and merge ( rebase 선행 필요) : 커밋 간소화
◦
rebase and merge : 커밋 그래프 유지
FROM | TO | HOW (1st) | HOW (2nd) |
main | None | ||
feature (from develop) | develop | squash | rebase |
sub feature | feature | squash | rebase |
release (from develop) | main | merge | rebase |
release (from develop) | develop | merge | rebase |
hotfix (from main) | main | merge | rebase |
hotfix (from main) | develop | merge | rebase |
TIP: 깃헙 리베이스 머지와, 로컬 리베이스 의 차이!
로컬 리베이스: 리베이스된 코드에 (커밋 해시값 달라짐) 에 다시 리베이스를 하게 되면, 같은 내용의 커밋이 올라가 있으면 스킵하고 지나갑니다. (커밋 내용 해쉬값을 비교)
깃헙 리베이스 머지: 같은 내용의 커밋이 있어도 아이디가 다르면 다른 걸로 인식하고 새로 커밋이 생기는 것처럼 보여주는데, 올리시면 스킵 됩니다.
TIP2: Conflict 예방책
main에 머지된 develop의 commit을 건드리지 않는것이 좋습니다. 수정이 필요하다면 추가 커밋.
한번 쓰고 폐기 되는 브랜치( feat, release, hot-fix) 는 rebase 가 편하지만, 계속 해서 들고가는 브랜치(develop) 에서는 commit id 가 변경되어 올라가기 때문에 다른 commit으로 인식되어 분기가 꼬입니다.
정리
전제: 로컬에서 병합 하는게 아니라, github에서 PR을 통해서만 병합
머지 하는 쪽에서 머지 대상을 리베이스 해갈 수 있으면, Rebase and merge or Squah and merge
*** rebase가 선행 되어야 합니다. *** 안그러면 커밋 아이디가 변경된 것이 계속 충돌이 발생합니다.
•
가능 브랜치
◦
feature, hotfix (from main to main)
•
로컬에서 작업후, 리베이스해서 올릴 수 있습니다.
머지 하는 쪽에서 머지 대상을 리베이스를 해갈 수 없으면 Merge or Rebase and merge
•
가능 브랜치
◦
develop, release, hotfix(from main to develop)
블로그 메인