git- rebase

2022. 12. 11. 22:52카테고리 없음

728x90

<merge로 두 브랜치 합치기>

<rebase로 두 브랜치 합치기>

rebase 명령으로 한 브랜치에서 변경된 사항을 다른 브랜치에 적용할 수 있다.

* rebase 명령어로 일어나는 일

일단 두 브랜치가 나뉘기 전인 공통 커밋으로 이동

-> 그 커밋부터 지금 checkout 한 브랜치가 가리키는 커밋까지 diff를 차례로 만들어 어딘가에 임시저장

-> rebase 할 브랜치(experiment)가 합칠 브랜치(master)가 가리키는 커밋을 가리키게 함

-> 아까 저장해 놓았던 변경사항 diff를 c4'에 차례대로 적용

c4의 변경사항을 c3에 적용

그리고 나서 master 브랜치를 Fast-forward 시킨다.

* rebase로 합치는 게  히스토리가 선형으로 좀 더 깨끗한 히스토리를 만든다.

일을 병렬로 진행해도 rebase 하고 나면 모든 작업이 차례대로 수행된 것처럼 보인다.

Rebase를 하든지, Merge를 하든지 최종 결과물은 같고 커밋 히스토리만 다르다는 것이 중요하다

 

<Rebase 활용>

토픽 브랜치 server에서 갈라져 나온 토픽 브랜치 client가 있다고 하자.

이때 테스트가 덜 된 server 브랜치는 그대로 두고 client 브랜치만 master로 합치려는 상황을 가정해보자

이때 사용하는 명령어: git rebase --onto master server client

-> 이 명령은 master 브랜치부터 server 브랜치와 client 브랜치의 공통 조상까지의 커밋을

   client 브랜치에서 없애고 싶을 때 사용한다.

  client 브랜치에서만 변경된 패치를 만든 후,  master 브랜치에서 client 브랜치를 기반으로 새로 만들어 적용한다.

다른 토픽 브랜치에서 갈라져 나온 토픽 브랜치를 Reabase 하기

이제 master 브랜치로 돌아가서 Fast-forward 시킬 수 있다.

git checkout master
git merge client

master 브랜치를 client 브랜치 위치로 진행시키기

server 브랜치의 일이 다 끝나면 

git rebase basebranch이름 topicbranch이름  라는 명령으로 

checkout 하지 않고 바로 server 브랜치를 master 브랜치로 Rebase 할 수 있다.

->즉, 토픽 브랜치를 checkout하고 베이스 브랜치에 Rebase하는 명령

git rebase master server

그 결과는 master 브랜치에 server 브랜치의 수정 사항을 적용한 것.

master 브랜치에 server 브랜치의 수정 사항을 적용

그리고 나서 master 브랜치를 Fast-forward 시킨다.

git checkout master
git merge server

모든 것이 master 브랜치에 통합됐기 때문에 client나 server 브랜치는 삭제해도 된다.

*브렌치를 삭제해도 커밋 히스토리는 최종 커밋 히스토리 같이 여전히 남아있다.

git branch -d server
git branch -d client

최종 커밋 히스토리


<Rebase의 위험성>

이미 공개 저장소에 push 한 커밋을 Rebase 하지 마라

 

예제로 알아보자

중앙 저장소에소 clone 하고 일부 수정을 아래와 하였다.

이제 팀원 중 누군가 커밋, Merge 하고 나서 서버에 Push 한다.

이 리모트 브랜치를 내 로컬에  Fetch, Merge 하면 아래와 같다.

그런데 push 했던 팀원은 Merge 한 일을 되돌리고 다시 Rebase 한다.

서버의 히스토리를 새로 덮어 씌우려면 git push --force 명령을 사용.

이후에 저장소에서 내 로컬로 Fetch 하고 나면 아래 그림과 같은 상태가 된다.

이렇게 짬뽕이 되버린다.

git pull 명령으로 서버의 내용을 가져와서 Merge 하면

같은 내용의 수정사항을 포함한 Merge 커밋이 아래와 같이 만들어진다.

같은 Merge를 다시 하는 상황 발생

이렇게 되면 같은 커밋이 두개 있다.(C4, C4') .

애초에 서버로 데이터를 보내기 전에 Rebase로 커밋을 정리했어야 했다.

 

<해결책>

이 상황일 때 서버의 내용을 가져와서 같은 Merge 다시 할 게 아니라 

git rebase teamone/master 명령을 실행하면 해결된다.

강제로 덮어쓴 브랜치에 Rebase 하기

아니면 아예 깔끔하게 git pull 명령을 실행 할 때 옵션을 붙여서 

git pull --rebase 명령어로 저런  문제를 미리 방지하자.

 

로컬 브랜치에서 작업할 때는 히스토리를 정리하기 위해 Rebase 할 수도 있지만,
Push로 내보낸 커밋에 대해서는 절대 Rebase 하지 말아야 한다.
728x90