git은 서로 다른 작업을 하기 위한 별도의 공간을 생성할 때, 브랜치를 생성할 수 있습니다.
각자 작업한 사항을 하나로 합칠 때, 합치는 방법으로는 merge와 rebase가 있습니다.
Merge
진행 과정
-
기능 구현을 위해서 해당 기능을 구현하기 위한 브랜치를 생성
-
기능 구현이 되는 경우, 해당 기능을 main 브랜치에 merge 함
git checkout main
git merge branch-1
Fast-forward
가리키고 있던 commit을 merge할 브랜치의 commit으로 이동하는 것이 fast-forward입니다.
두 브랜치의 base가 같을 때, 최신 버전을 따라가는 것!
base가 다른데 merge한다면?
git fetch upstream main
git merge upstream/main
base가 다른데 merge하는 경우, git은 자동으로 새로운 merge commit을 새로 만듭니다. 바로 merge remote-tracking branch라는 commit을 생성합니다.
즉, git이 별도의 최적 공통 조상을 자동으로 찾고, feat 브랜치가 해당 commit을 가리키도록 변경합니다.
Conflict
만약 로컬과 원격 모두 같은 파일을 수정해서 자동 merge를 할 수 없는 경우, 이를 conflict이라고 합니다.
충돌이 발생한 파일을 가면 HEAD(현재 브랜치), 아래가 merge할 브랜치로, 두 파일의 충돌 사항을 볼 수 있으며, 이를 수정해야 합니다.
수정 후, 이 파일을 git add하면, 충돌이 해소되어 이전과 마찬가지로 자동적으로 merge commit이 정상적으로 생성됩니다.
Github의 3 가지 Merge 방식
1. Create merge commit
Fast-forward를 하는 것이 아니라, 하나의 merge commit을 생성해서 merge를 진행
2. Squash and Merge
하나의 merge commit을 생성해서, 해당 commit을 가리키도록 함
feature에서 작업했던 모든 commit들을 하나의 commit으로 통합해서 merge를 진행
그래서, 한 기능에 commit이 너무 많은 경우, 특정 기능에 대한 commit을 하나만 두어서 가독성이 좋아질 수 있음
PR 단위마다 해당 commit이 이름으로 작성되어서 누가 작업했는지 보기 쉽습니다.
git checkout main
git merge --squash feature
git commit -m "squash merge message"
3. Rebase and Merge
feature에서 작업한 사항들을 main 브랜치로 최상단에 복사 붙여넣기 하는 작업
한 줄로 모든 commit이 저장되어 오히려 더 난잡해 보일 수 있습니다.
git checkout feature
git rebase master
git checkout master
git merge feature
Rebase
방식 | 설명 |
---|---|
Merge | 브랜치를 합침 |
Rebase | Merge보다 깨끗한 commit history를 만듦 commit history가 merge와 다르게 선형적으로 그려짐 |
현재 branch의 Base를 재설정(변경)하여 합치는 것입니다.
주의해야 할점은 그냥 Base 포인터만 바뀌는 것이 아니라, Base가 바뀔 commit 들을 복사하여 연이어 붙이는 것입니다.
merge를 한 코드 결과와 rebase를 한 결과는 같아야 합니다.
원격 저장소로 올라간 commit을 rebase하는 경우, 같은 commit이지만 id가 달라져서 비권장된다고 합니다.
Cherry pick
원하는 변경점만 고를 수 있습니다.
- main에 직접 push
git checkout main
git cherry-pick <commit id>
git push origin main
- 브랜치를 생성 후, 해당 브랜치에서 cherry-pick 진행
main 브랜치로의 merge PR을 요청한 후,
git checkout main
git checkout -b <생성할 브랜치 이름>
git cherry-pick <commit id>
git push origin cherry
-
여러 개 가져오고 싶은 경우
공백으로 구분하여 여러 commit들 지정 가능
git cherry-pick 29dk349 18fef123 38sdf192
-
특정 구간에 연속된 commit들을 가져오는 경우
git cherry-pick 29dk349..38sdf192
conflict가 발생하면?
- 충돌 해결을 위해 코드를 수정
git add
명령어로 수정된 코드를 addgit cherry-pick --continue
명령을 수행
주의할 점으로는 같은 commit 이름이 생겨서 알아보기 어려울 수도 있습니다.