병합
프로젝트에서 main 브랜치가 존재한다.
그럼 다른 브랜치에서 작업을 하고 이를 main 브랜치에 반영해야 한다.
분리된 브랜치를 하나의 브랜치로 합치는 작업을 병합이라고 한다.
각각의 브랜치에서 수정된 내용을 하나의 브랜치로 병합한다.
과거 수동(노가다)으로 코드를 하나하나 바꾸는 것은 정말 어렵고 귀찮은 일이었다.
깃을 사용해 자동 병합이 가능해지며 개발자의 삶이 윤택해졌다.
깃의 자동 병합은 원본을 기준으로 두 파일의 변경 이력을 비교하고, 변경된 파일 내용이 발견되면 자동으로 수정된 코드 내용을 병합한다.
그러나 자동으로 병합이 불가능한 것도 존재하는데, 이를 충돌이라고 한다.
병합 방식
병합 방식으로는 크게 2가지가 있다.
- Fast-Forward 병합
- 3-way 병합
실습 환경을 구축해보겠다.
git init
mkdir merge
cd merge
vi merge.txt
-> 아무거나 입력 Hello, Merge
git add .
git commit -m "first commit"
이제 두 병합 방식에 대해 알아보자.
Fast-Forward 병합
Fast-Forward 병합의 특징은 다음과 같다.
- 일반적으로 혼자 개발할 때 사용
- 혼자 개발할 때는 브랜치가 생성된 커밋에 따라 순차적으로 분기된다. 또한 보통 코드 수정도 순차적
- 브랜치가 분기되면 전체 커밋 그림으로 보면 모든 변경사항이 순차적
- 순차적 커밋에 맞추어 병합을 처리하는 방법이 Fast-Forward 병합
실습을 위해 새로운 feature 브랜치를 생성하고 feature 브랜치로 switch한다.
git branch feature
git switch feature
실습을 그대로 수행했다면 feature 브랜치와 master 브랜치의 시작 위치가 동일하다.
이제 앞서 작성한 merge.txt를 수정한다. 그리고 수정한 내용을 커밋한다.
git commit -m "first update merge.txt"
이제 feature 브랜치가 master 브랜치보다 커밋이 하나 더 있다.
그리고 feature 브랜치에서 merge.txt를 수정하고 커밋을 2개만 더 해보자.
그럼 master와 feature 브랜치는 시작점은 동일하지만 feature 브랜치가 커밋이 3개 앞선다.
그림은 다음과 같다.
서로 다른 브랜치이지만 순차적으로 커밋을 했기 때문에 일직선으로 볼 수 있다.
이러한 모양의 브랜치에서 병합 작업을 할 때 Fast-Foward 방식의 알고리즘이 적용된다.
깃의 merge 명령어는 브랜치를 병합한다. merge 명령어는 현재 브랜치를 기준으로 다른 브랜치의 모든 커밋을 병합한다.
이제 main or master 브랜치로 가서 git merge 명령어를 입력하면 된다.
git switch main
git merge feature
이러면 그림 구조는 아래와 같이 변한다.
Fast-Forward 병합은 작업한 브랜치를 원본 브랜치에 병합할 때 작업한 브랜치의 시작 커밋을 원본 브랜치 이후의 커밋으로 가리킨다.
이는 단순히 커밋 위치를 최신으로 옮기는 것과 비슷하다.
3-way 병합
여러 개발자와 협업하는 경우 대부분 3-way 병합을 사용한다.
실습을 진행해보자. 이번에는 hotfix라는 브랜치를 만들고 스위치한다.
mkdir hotfix
vi task.txt
//간단한 내용 작성
git commit -m "first commit"
git branch hotfix
git switch hotfix
vi task.txt
//충돌 안나게 아무 내용이나 작성
git add .
git commit -m "write task"
vi task.txt
//이후 task.txt 내용 수정
git add .
git commit -m "update task"
아래는 현재까지 브랜치의 모습이다.
이제 main or master로 돌아간다.
그리고 task.txt에 내용을 작성하고 커밋을 2개 정도 진행해보자.
그렇다면 아래와 같은 그림이 현재 브랜치의 모습이다.
이제 두 브랜치로 갈라지는 모습을 확인할 수 있다.
브랜치 모양이 갈라지는 형태로 나올때는 Fast-Forward 방식을 적용할 수 없다.
이때 바로 3-way 방식을 사용해야 한다.
공통 조상
두 브랜치를 병합하려면 먼저 분할 기준인 공통 커밋을 찾아야 한다. 이를 공통 조상 커밋이라고 한다.
공통 조상 커밋을 포함하는 브랜치와 새로운 두 브랜치, 이렇게 3개를 하나로 병합해야 한다.
브랜치가 3개 있다고 해서 3-way 병합이라고 한다.
깃은 3-way 병합을 할 때 공통 조상 커밋을 자동으로 찾아준다.
이는 다른 VCS보다 서로 다른 브랜치를 편리하게 병합할 수 있는 깃의 장점이다.
병합 커밋
3-way 병합은 두 블랜치에서 공통 조상 커밋을 자동으로 찾아 주며, 공통 조상 커밋을 기준으로 브랜치를 병합한다.
그리고 병합을 성공적으로 완료한 후에는 새로운 커밋을 추가로 하나 생성한다.
새로 생성된 커밋을 병합 커밋이라고 한다.
병합 커밋은 부모 커밋이 2개라는 특징이 있다.
그럼 이제 hotfix 브랜치를 main or master 브랜치에 병합해보자.
git switch main
git merge hotfix
성공적으로 병합되면 병합 커밋이 하나 추가된다. 그 과정에서 우리는 vi로 들어가 병합 메시지를 작성했다.
참고
Merge branch hotfix와 같은 메시지가 자동으로 들어간다. --edit 옵션을 통해 이 메시지를 수정할 수도 있다.
만약 충돌이 발생하면 자동으로 커밋이 되지 않는다. 충돌을 개발자가 직접 수동으로 해결하고 커밋을 해야 한다.
결국 깃이 알아서 merge하면 Fast-Forward 또는 3-way를 적용해주는거였네
다음은 rebase에 대해 알아보자.
참고자료
GIT 교과서(이호진님)
https://product.kyobobook.co.kr/detail/S000001834368
댓글