1. Fast-foward merge
master 브랜치에서 다른 branch를 생성하는 순간, 그 생성 시점의 기준이 됐던 commit 지점을 base라고 한다.
즉 base란 master브랜치와 새로 생성된 branch 두 브랜치가 공통으로 가지고 있는 commit 상태이다.
아래 흐름을 보면 master 브랜치와 dev1 브랜치가 공통으로 참조하는 commit은 (base) 동일 선상에 위치하고 있는 상황이다.
(이 후에 나오는 three-way merge를 보면 다른 선상에 위치하고 있는 상황이 어떤 것인지 확인할 수 있다. )
이 때 두 브랜치를 Fast-foward 상태에 있다고 한다.
fast-forward 관계에 있는 브랜치에서 git merge 명령을 입력하면 새로운 commit이 생기지 않는다.
merge 작업이 완료 된 새로운 커밋을 생성하는 것이 아닌, 이전 시점의 브랜치(여기서는 master)에서 앞서가는 브랜치를 가리키도록 할 뿐이다.
이러한 흐름을 fast-forward(빨리감기)라고 부른다고 한다.
2. 3-way merge
3-way merge의 경우 다른 방식으로 작동한다.
두 브랜치 모두 base에서 commit을 진행한 뒤 추가 작업 + 커밋을 해서 진행된 상태가 되었다.
두 브랜치 모두 base commit 시점에 위치하지 않는 상황이다.
이 때 git merge 명령을 실행하면 fast forward와 달리, 두 브랜치를 병합해서 새로운 commit이 생성된다.
이와 같은 merge를 3-way merge 라고 한다.
3-way로 불리는 이유는 내용을 병합할 때, base와 각 브랜치 2개가 참조하는 commit을 기준으로 병합을 진행하기 때문이다.
3-way merge를 이용할 경우, commit을 작성할 수 있기 때문에 어떤 내용으로 병합이 되었는지 확인할 수 있다는 장점이 있지만,
다르게 생각하면 모든 feature branch를 merge 할 때마다 commit이 남기 때문에 master 브랜치를 공유하는 개발자가 많고, 프로젝트의 규모가 크다면 branch history가 지저분해지기 쉽다.
또한 커밋 내역이 다른 프로젝트의 커밋들과 겹쳐진 상태로 유지되기 때문에 구분하기 어려워진다.
이런 상황을 해결하기 위해 rebase를 사용하여 fast-forward merge를 할 수 있다.
3. rebase
rebase란 결국 말 그대로 base를 다시 만든다는 것이다.
three-way와 비교해서 보면 아래 그림과 같다.
master branch와 master 브랜치에서 파생되었던 dev1 브랜치가 있다면,
기존에 dev1 브랜치가 참조하고 있던 기준 base commit을 master 브랜치의 최신 버전으로 바꿔주는 것이다.
이렇게 될 경우 커밋이 섞이지도 않고, 새로운 commit이 생성되지도 않기 때문에 history가 훨씬 깔끔해진다.
다만 혼자서 dev1 branch에서 작업하고 있다면 언제든지 Rebase 를 할 수 있지만 다른 개발자와 함께 작업하고 있다면 위험할 수 있다.
rebase를 하게 되면 가르키고 있는 기준 base를 변경해야 하는데,
이 때 base를 변경하게 되면 !
기존의 commit 을 변경하는 것이 아니라, 새로운 커밋을 만들게 되는 것이기 때문이다.
즉 겉으로는 똑같지만 사실은 다른 커밋으로 변경되는 것 .
즉 위 그림에서 * 가 표시된 커밋들은 기존의 커밋과 동일한 커밋들이 아닌, 똑같아 보이지만 다른 커밋들이다.
누군가 *가 찍히지 않은 커밋에서 작업을 하고 있었다면 자기가 작업하던 커밋이 사라져 버리게 되는 것.
그렇기 때문에 다른 개발자와 함께 같은 branch위에서 작업하고 있거나, 혹은 이미 histroy 가 server에 업로드된 경우라면 절대 Rebase 하면 안된다.
서버에 업데이트 되지 않는 나의 local 에 대해서는 자유롭게 해도 된다.
* 새로운 작업을 마치고 push 하기 전
1. Master branch 로 이동하여 remote master을 pull 받는다.
2. 내가 push 할 Feature branch 로 이동한다.
3. `git rebase -i master` 를 진행한다.
[ Rebase 하는 동안 squash 진행할 때에는 ]
1. 가장 오래된 commit을 pick 한다.
2. 다른 커밋 메세지는 가장 오래된 commit을 기준으로 squash 한다.
3. 다른 커밋의 작업 내역이 없어지는 것이 아닙니다.
4. Esc -> :wq! 로 창에서 빠져나온다.
+ rebase --onto
여러개의 브랜치를 만들고 그 브랜치 위에 브랜치를 만들고 chaining 해서 만들 때 유용하게 쓸 수 있다.
a -> b -> c -> d (master)
e -> f -> g (service)
h -> i (UI)
마스터를 개발하다, c지점에서 service 브랜치를 만들어서(e) 현재 g까지 작업하고 있는 상황이다.
만들어가던 서비스 브랜치에 기반하는 UI 브랜치를 만들기 위해 f지점에서 새로운 브랜치를 만들어서(h) i까지 작업했는데,
다시 보니 굳이 기존에 브랜치로 만들었던 service branch 없이 UI branch 만 merge 해도 되겠다 싶을 때 사용할 수 있는 방법이다.
새로 개발하고 있는 service에 의존적인 UI를 만들다가,
굳이 service가 필요없어서 service 없이 UI 브랜치만 master branch에 merge하고싶은 상황.
마스터 -> 브랜치1 -> 브랜치2 인 상황에서 브랜치2에서 바로 마스터로 rebase 하기 위함.
1) a -> b -> c -> d (master) -> e -> f -> g (service)-> h -> i (UI)
2) a -> b -> c -> d (master) -> h -> i (UI)
1)방식이 아니라, 2)방식으로 진행하고 싶을 때. h - i (UI)가 d(master branch) 를 가리키게 하기.
git rebase --onto d
+Cherry-pick
다른 브랜치에 있는 커밋을 선택적으로 현재 브랜치에 적용시키고 싶을 때
필요한 commit만 pick !
a -> b -> c -> d (master)
e -> f -> g (service)
에서
a - b - c - d - f (master) 를 만들고 싶을 때
여기서 g말고 f만 merge 하면 안될까? 라고 했을때
git cherry-pick <commit hash>
즉
git cherry-pick f2b9178 < -- 이런식.
'Frontend Study - 2 > git' 카테고리의 다른 글
Git 사용법 Process (0) | 2022.06.30 |
---|