브랜치 또는 특정 커밋의 내용을 현재 브랜치에 병합하는 것
Merge의 3가지 동작 : Fast forward / 3-Way Merge / Rebase
Merge의 3가지 전략 : Merge (Merge Commit) / Squash and Merge / Rebase and Merge
$ git merge <branch> or <commit>
Fast forward / 3-Way Merge / Rebase
merge할 브랜치가 가리키고 있던 commit이 현 브랜치가 가리키는 것보다 앞서 진행한 commit이기 때문에 master 브랜치 포인터는 최신 commit으로 이동한다.
예를 들어, 현재 C2(master)를 부모로 가진 iss53에서 작업중이라고 가정해보자. 여기서 C2(master)을 부모로 가진 hotfix 브랜치를 생성해 commit하고 hotfix에서 master 브랜치를 merge 해야 한다.
master 브랜치는 hotfix보다 앞서 진행한 commit이기 때문에 별도의 추가적인 merge가 필요 없는 상황이다. 따라서 단순히 포인터를 최신 커밋으로 옮기면 되고 이러한 방식을 Fast forward 라고 부른다.
병합할 때 별도의 커밋을 생성하고 master 브랜치는 그 커밋을 가리키도록 이동한다.
현재 master가 가리키는 커밋(C4)은 merge할 브랜치(iss53)의 조상이 아니다.
따라서 Fast forward가 적용되지 않는다.
따라서 공통 조상은 C2가 되고 각 브랜치가 가리키는 커밋 C4, C5와 공통 조상 C2를 이용해 새로운 커밋 C6을 만들고 3-Way Merge를 수행하게 된다. 이런 commit은 부모가 여러개이며 Merge Commit이라고 부른다.
두 브랜치에서 같은 파일을 동시에 수정하고 Merge 하면 Conflict가 발생한다. 작업 내역을 비교하면서 merge할 부분을 적용해야 한다.
<<<<<<< HEAD
내가 작업한 내역
=======
merge하려고 한 브랜치의 작업 내역
>>>>>>> fjdkweqwj123dkdo41jf92kdd71j28
// 다운로드를 통해 충돌난 커밋 번호의 식별자
$ git pull origin master
...
warning: Cannot merge binary files: 이미지.jpg (HEAD vs. 439dc8c08869c342438...)
Auto-merging 이미지.jpg
CONFLICT (add/add): Merge conflict in 이미지.jpg
Automatic merge failed; fix conflicts and then commit the result
⇒ $ git checkout
을 사용해 해결 가능하다.
$ git checkout HEAD 이미지.jpg
$ git add 이미지.jpg
$ git commit -m "내가 작업한 파일 사용"
$ git checkout 439dc8c0 이미지.jpg
$ git add 이미지.jpg
$ git commit -m "원격지 작업 파일 사용"
$ git checkout HEAD 이미지.jpg
$ git mv 이미지.jpg 이미지-me.jpg // 내 파일 이름 변경
$ git checkout 439dc8c0 이미지.jpg
$ git mv 이미지.jpg 이미지-remote.jpg // 원격지 파일 이름 변경
$ git rm 이미지.jpg // tracked 된 파일 untracking
$ git add 이미지-me.jpg
$ git add 이미지-remote.jpg
$ git commit -m "두 개의 파일 모두 사용"
브랜치의 공통 조상이 되는 base를 다른 브랜치의 커밋 지점으로 바꾸는 것
참고 사이트 : https://velog.io/@godori/Git-Rebase
Rebase 하려는 브랜치 commit들의 변경 사항을 Patch 라는 것으로 만든 후 어딘가에 임시 저장한다.
그리고 이를 master 브랜치에 하나씩 적용하여 새로운 커밋을 만든다.
ex. feature를 master에 rebase 하는 과정
$ git checkout feature
$ git rebase master
$ git checkout master
$ git merge feature
Step1
$ git checkout feature
feature 브랜치로 체크아웃한다. head는 feature을 가리킨다.
Step2
$ git rebase master
master와 feature의 공통 조상인 base 커밋부터 현재 브랜치까지의 변경사항(▵1, ▵2) 을 구해서 patch로 임시 저장한다.
Step3
$ git checkout master
head를 master로 변경한다.
Step4
$ Applying f1
$ Applying f2
head가 가리키고 있는 m2에 변경사항 ▵1를 적용하여 새로운 커밋 f1'를 생성한다.
f1'에 변경사항 ▵2를 적용하여 새로운 커밋 f2'를 생성한다.
Step5
feature이 f2'를 가리키도록 한다.
Step6
$ git merge feature
feature를 master로 Fast forward merge 하여 완료한다.
Merge (Merge Commit) / Squash and Merge / Rebase and Merge
브랜치를 merge 한다는 목적은 같지만, 커밋 히스토리가 기록되는 방식이 달라짐
우리가 알고 있는 일반적인 머지 전략이다.
여러 개의 커밋을 하나로 합치는 머지 전략이다.
merge할 브랜치의 commit을 전부 하나의 commit으로 합친 뒤, 타켓 브랜치에 commit하는 방식이다.
브랜치 히스토리들의 베이스를 변경하는 기능으로, A 브랜치의 변경 사항(commit)이 마치 B 브랜치에서 변경된 것처럼 바꿀 수 있게 하는 기능
merge는 비파괴적(non-destructive)이다.
각각의 브랜치에서 이루어진 commit들은 분기가 합쳐진 후에도 그대로 유지되기 때문에 나중에 코드가 변경된 브랜치를 좀 더 쉽게 찾아갈 수 있다.
하지만 merge는 불필요한 commit도 히스토리에 남기 때문에 히스토리 그래프의 가독성이 떨어진다는 단점이 있고, 대안으로 rebase라는 옵션을 사용한다.
rebase는 master 브랜치의 변경점들을 모두 반영하면서 feature 브랜치를 master 브랜치의 끝 부분에서 시작하도록 이동시킨다. merge와 달리 새로운 commit을 생성하여 합치는 것이 아니라, 원래 브랜치의 commit 마다 변경점이 반영된 새 commit으로 변경한다.
rebase는 브랜치를 한 번 정리해주기 때문에 깨끗한 commit 히스토리를 만들 수 있다. 즉, 불필요한 commit 내역은 포함이 되지 않는다.
rebase는 public 브랜치에서 하지 않아야 한다.
예를 들어 feature 브랜치에서 rebase를 하는 경우로 가정해보자.
feature에서 rebase를 하면 master의 모든 commit이 feature 브랜치의 끝 부분으로 올라간다. 문제는 다른 사람들은 아직 master 브랜치를 사용하고 있다는 것이다. rebase가 새로운 commit으로 바꾸기 때문에 master 브랜치가 나와 다른 경우가 생긴다. 이런 상황을 방지하기 위해 rebase는 master 브랜치에서 하는 것을 권장한다.
Thanks to 팀장님 🙂🙃🙂