Fast Forword와 merge 그리고 rebase 정리

IT 지식/Git|2019. 12. 13. 00:01

5년차가 될정도로 개발을 어느정도 진행했지만 아직까지도 git에 대한 정리가 잘 되지 않는다.

 

공부도 하고 정리도 했었지만 실상 회사에서 주구장창 브랜치 만들고 머지만 해서 진행했기 때문에 fast forword를 하고 merge, rebase하는 것과 안하고 하는것의 방법을 잘 알지 못했다.

 

개념은 알아도 직접 많이 해보지 않으면 그게 와닿지 않는 것 같다.

그럼 현재 이직한 회사에서는 이 방법을 많이 사용하기에 정리를 해서 까먹지 않도록 해보자.

 

Merge

Merge는 이미 우리가 익히 알고 있듯이 두 개의 브랜치를 합치는 걸 의미한다. 그럼 fast forword를 하고 merge를 하면 어떻게 되는지 보자.

현재 이렇게 되어있는 상황에서 feature/si를 fast forword 포함해서 merge 해보겠다.  우선 master로 checkout하고 머지하려고 하는 feature/test 브랜치 우측클릭하여 머지를 해보자.

그럼 master가 feature/si의 커밋 위치로 가있는 것을 알 수 있다.

그럼 다시 마스터를 커밋하기 전으로 돌리고 다시 non fast forword를 해보자.

우선 다시 돌리자.

그리고 source tree에서는 global옵션 - Git에서 "병합 시 fast-forword를 사용하지 않고 항상 커밋을 생성"을 선택하고 다시 merge 해보자.

그러면 아래와 같은 모양으로 feature/si의 브랜치는 그대로 있고 master의 브랜치는 더 앞으로 가있는 것을 볼 수 있다.

 

그럼 과연 fast forword가 정확히 무엇인가?? 

궁금하다.

 

찾아보니 fast forword는 병합하려는 브랜치에 새로운 커밋이 없는 상황에서 발생되며 merge가 된 브랜치의 최신 커밋으로 head가 옮겨지는 것을 말한다.

 

위의 예에서 보면 master에서 분기된 feature/si브랜치가 새로운 커밋을 가지고 있고 master는 feature/si가 분기 된 이후에 새로운 커밋이 없는 상황이었다. 이때 git merge feature/si를 하게 되면 master는 feature/si 마지막 커밋으로 옮겨지고 한줄로 이어서 보여지는 아래 그림 오른쪽 처럼 되게 된다. 

 

하지만 이는 이력관리하기가 어렵기 때문에 merge하는것처럼 보여주고 이력관리를 위해서 --no-ff 옵션을 붙여서 머지하게 되면 왼쪽처럼 히스토리도 남고 master와 breanch의 위치가 구분되게 된다.

Rebase

rebase는 feature 브랜치의 커밋을 새로 rebase되는 커밋의 parent commit으로 된다. 이렇게 하게 되면 히스토리가 깔끔하게 보인다.

우선 rebase를 진행하기 위해 feature 브랜치로 checkout하고 rebase를 진행할 마스터 브랜치를 누르고 리베이스를 진행한다.

그럼 아래처럼 master위에 feature 브랜치가 위로 붙는 구조가 될것이다.  

이 상태에서 마스터로 체크아웃 하고 feature/si로 merge를 하면 fast forword가 되어 둘이 동일한 커밋을 바라보게 된다.

명령어로 정리하면 다음과 같다.

git checkout feature/si
git rebase master
git checkout master
git merge feature/si

 

 

하지만 이렇게 되면 브랜치의 히스토리를 확인하기가 어렵다. 만약 히스토리를 확인하고 싶으면 아래 명령어를 사용하면 히스토리를 확인할 수 있다.

git checkout feature/si
git rebase master
git checkout master
git merge --no-ff feature/si

 

 

어렵다 ㅋㅋ git은 해도해도 헷갈린다. 

만약 참고하시고 이상한 부분 있으면 말씀 부탁드립니다~

댓글()

Git Rebase 도중 한번 이상 충돌 해결 방법

IT 지식/Git|2018. 6. 23. 22:57

Git에서 브랜치를 rebase 하는 도중에 충돌이 여러번 발생하였을때 해결하는 방법에 대해 알아보자.

먼저 기준이 되는 브랜치 master에 test.txt라는 파일을 만들고 내용을 작성하고 커밋을 진행하자.

 

그리고 리베이스를 진행할 브랜치인 conflict 브랜치에 test.txt를 생성하고 두번 커밋을 진행하자.

그리고 master에 리베이스를 진행하면 먼저 첫번째 충돌이 발생한다.

그러면 test.txt 파일을 수정하고 나서 스테이지에 다시 올리고 액션 메뉴에서 재배치 계속을 눌러 진행한다.

그러면 두번째 충돌이 발생하고 마찬가지로 해결 후 재배치 계속을 누르면 성공적으로 리베이스가 진행된것을 확인할 수 있다.

이렇게 두번의 충돌이 발생하는 이유는 아래의 그림을 살펴보면 알겠지만 변경이 델타 1, 델타 2 두번이 이루어져있고 이를 마스터에 적용을 진행을 하면서 여러번 같은 파일에 충돌을 해소해야 하는 문제가 발생한 것이다. 

이렇게 귀찮은 짓을 반복하고 싶지 않다면 브랜치에 있는 여러 커밋들을 하나로 합친 후에 마스터 브랜치에 합치면 단 한번만 충돌을 해결할 수 있다. 

여러 상황에 대해 많이 테스트 해보고 진행해보면서 문제를 해결해 보는 능력을 길러야겠다.

 

깃은 svn보다 확실히 편하지만 어렵다.

 

 

 

댓글()

Git Rebase 도중 충돌 (conflict) 해결 방법

IT 지식/Git|2018. 6. 23. 22:24

저번부터 계속해서 rebase에 대해 알아보았다. 그러나 생각보다 rebase를 진행하다보면 충돌이 나는 경우가 많다. 

간단하게 리베이스에서 발생한 충돌을 해결해보자.

우선 master에서 c.txt를 만들고 커밋을 진행해보자.

 

그리고 conflict 브랜치에서 c.txt를 만들어서 파일내용에 conflict branch commit으로 저장하고 커밋을 하자.

 

그럼 이제 master 브랜치로 conflict 브랜치를 rebase하여 merge를 진행해보자. 그러면 다음과 같이 충돌이 발생하게 되고 rebase가 멈추는것을 볼 수 있다.

 

그럼 충돌된 내용이 무엇인지 확인해보자.

몬가 이상한것을 확인할수있다.

바로 HEAD 부분에 원래 merge중에 충돌이 발생하면 내 코드가 나오고 하단에 충돌이 발생한 코드가 나오기 마련이다. 하지만 반대로 되어있다. 

그 이유는 아래 그림을 보면 알겠지만 리베이스 도중에 리베이스에 기준이되는 master 브랜치로 head가 옮겨지면서 순서가 뒤바뀌게 되는것이다. 잘 숙지하고 오해하지 않도록!

 

그럼 충돌이 발생한 코드를 수정해보자. 충돌이 발생한 c.txt파일에 충돌내역을 수정하고 저장을 한 뒤에 스테이지에 파일을 올려놓는다. 그리고 action 메뉴에서 재배치 계속을 눌러 리베이스를 마무리한다.

 

그러면 충돌이 해소가 되고 두 개의 브랜치가 성공적으로 리베이스 작업이 완료된것을 알 수 있다.

실무에서는 더 복잡하게 게 충돌이 일어날 가능성이 크다. 다음 시간에 조금더 복잡한 상황에서 발생하는 사례를 공부해보자.

댓글()

Git 대화형 rebase를 사용한 커밋 순서변경, 합치기 등등 방법

IT 지식/Git|2018. 6. 22. 00:28

저번에 공부했었던 rebase에 대해 더 공부해보자. 이번에 공부할 내용은 대화형 rebase를 통해 커밋한 내용을 지우거나, 순서를 바꾸거나 기존 커밋에 내용을 더 추가하거나 하는 내용을 확인해보자.

 

커밋 합치기

리베이스를 진행할 때 리베이스를 진행할 브랜치에 커밋된 내용이 길다고 가정해보자. 그러면 그 커밋마다 변경된 내용이 다 달라서 master에 리베이스를 진행할 때 여러번에 conflict를 해결해야 한다.

그래서 오늘 강의해주신 강사님이 말씀하시길 브랜치의 커밋을 하나로 합치고 나서 rebase를 진행하면 좋다고 하셨다. 그럼 합쳐보자.

우선 아래 이미지를 보면 c2와 c3의 커밋을 하나로 합쳐서 아래와 같이 마스터 브랜치에 합쳐보겠다.

우선 위와 같은 상황이 되도록 브랜치를 만들어서 진행해보면 다음과 같이 히스토리를 볼 수있다.

그럼 여기서 feature 커밋과 feature 2번째 커밋을 합쳐보겠다.

우선 대화형 리베이스에 경우 앞에 있는 커밋들에 대해 조정을 하는 것이기 때문에 조정하려고 하는 커밋의 바로 직전 커밋에서 조절을 시작해야한다. 

위에 상태에서는 feature 브랜치에서 마스터 커밋위치에서 우측 클릭을 하여 대화형 리베이스 모드에 진입한다. (이 부분은 앞으로 진행할 내용들도 동일하다.)

가장 최상단의 커밋을 누르고 이전 커밋과 합치기를 누른다.

그러고 난 후 커밋을 더블클릭하면 메시지를 변경할 수있다.

 

그러면 다음과 같이 합쳐진것을 확인할 수있다.

 

특정 커밋 없애기

이번에는 특정 커밋을 제거 하고 싶을 때 하는 방법을 알아보자.

위와 같은 상황에서 feature 커밋 2를 없애보자.

마찬가지로 바로 직전 커밋인 feature 커밋 1으로 커서를 두고 대화형 리베이스 모드에 들어간다.

그리고 지우고자 하는 커밋을 선택하고 삭제한다음 OK 를 누른다.

 

그러면 다음과 같이 커밋 히스토리가 변경된 것을 알 수 있다.

커밋 순서 바꾸기

커밋의 순서를 바꾸고 싶을 때 다음과 같이 진행한다.

동일하게 그 직전에 마우스를 놓고 대화형 리베이스 모드에 들어간다.

feature commit2 와 3의 순서를 바꿔보겠다.

변경을 원하는 커밋을 누르고 하단의 화살표를 통해 순서를 바꾸고 확인을 누르면 된다.

 

중간에 커밋내용 변경하기

커밋을 진행하다 보면 파일을 빼먹을때가 있다. 이럴경우 특정 커밋에 내용을 추가해주면서 방법을 알아보자

 

바로 직전인 마스터 대화형 리베이스를 선택한다.

그리고 해당 커밋에 amend 영역을 클릭하고 확인을 누른다.

그러면 해당 commit 부분이 리베이스 될때 멈추는 것을 볼 수 있다.

그 상태에서 변경하거나 추가하고 싶은 파일을 스테이지 다음과 같이 올린다. 여기서 중요한 것은 스테이지에 올린 후에 커밋을 진행한다 (커밋 옵션에서 마지막 커밋 수정을 눌러서 진행해야 한다.)

그리고 액션 메뉴에 있는 재배치 계속을 클릭한다.

 

 

여러 경우 리베이스에 대해 공부했다.

다음에는 리베이스 도중 conflict 해결에 대해 알아보자.

 

 

댓글()

Git의 rebase를 이용한 커밋 정리 (merge와 차이)

IT 지식/Git|2018. 6. 21. 23:26

Git을 처음 입사 후 진행했던 프로젝트에서 Gitlab을 통해 처음 접해보았다.

확실히 저장소 관리하는 방식과 커밋 전 단계가 제공되는 것 등등 편한 것이 많았다. 하지만 그 때 당시 딱히 팀원이 없었기에 히스토리 관리 및 flow 관리를 해야한다는 필요성을 알지도 못했고 듣지도 못했었다.

그러나 공부를 진행해보면서 git에 rebase라는 좋은 기능이 있다는 것을 알게되었고 배워보고 싶어 nhnent에서 제공하는 사내 교육에 참여하였다.

우선 첫 번째 글로 rebase와 merge에 차이를 설명하고 rebase를 진행해보자.

rebase란? 우선 rebase는 base를 다시 지정한다 (re-base)의 의미이다. base가 무엇인가? 다음 그림을 보자.

그림을 보면 master의 c4와 experiment 브랜치의 c3 커밋이 있다. 두 개의 커밋은 c2라는 같은 조상에서 시작되었다. 바로 이 c2가 base이다. 그럼 이 베이스를 다시 한다는 것은 어떤 의미일까?

여기서 중요한 개념이 rebase와 merge에 차이이다.

그림을 보면 두 개의 master와 experiment 브랜치는 서로 merge를 하였고, 그러면서 새로운 c5 커밋이 생겼다. 이 두개의 커밋이 합쳐져서 이제 하나의 뿌리로 시작하겠지만 커밋 히스토리를 보게되면 위와 같이 뿌리가 나눠져 있어서 히스토리를 찾아갈 때 보기가 어렵다.

이건 단순한 한가지 코드지만 만약 브랜치가 엄청 많아진다면? 정말 히스토리를 보기 어려울 것이다. 그렇기 때문에 리베이스 개념이 사용되는데 베이스를 다시 재정의하여 새롭게 커밋라인을 정리하여 히스토리를 깔끔하게 볼 수있게 해준다.

이 그림이 rebase가 완료된 그림이다.

브랜치가 사라지고 두 개의 브랜치의 base였던 c2를 기준으로 정리가 된것을 볼 수있다.

rebase 단계 계산 및 진행과정

현재 위와 같은 상황이라고 가정해보자. 현재 head는 feature 브랜치에 있고 아래 master branch를 향해서 rebase를 진행할 것이다.

그러면 c2까지의 변경내용에 대해 계산을 선 진행한 후 다음과 같이 변경 내용들을 master 브랜치 앞에 붙힌다.

그리고 master 브랜치를 새로 리베이스된 커밋 앞으로 fast-forward를 진행하면 다음과 같이 완료된다.

그럼 리베이스를 실습해보자.

rebase 하기

git의 기능을 편리하게 사용할 수 있도록 제공해주는 sourceTree를 사용해서 진행해보겠다.

우선 저장소를 먼저 생성하고 마스터 브랜치에 새로운 파일을 하나 추가하고 첫 번째 커밋을 진행한다.

그리고 마스터 브랜치에 파일을 하나 더 추가하고 한번더 커밋을 제공하면 다음과 같이 히스토리를 볼 수 있다.

그리고 feature 브랜치를 하나 생성한다.

생성이 완료된 feature로 체크아웃한 후 두 개의 커밋을 더 진행한다. 그리고 마스터로 돌아와서 한번도 커밋을 진행하면 다음과 같은 히스토리를 볼 수 있다.

그럼 여기서 feature 브랜치의 내용을 master로 rebase를 진행해보겠다.

우선 feature 브랜치로 checkout 진행 후 sourceTree에서 master branch를 우클릭한 후 현재 변경사항을 master에 재배치를 선택한다.

그러면 다음과 같이 rebase가 진행된 것을 볼 수 있다. 깔끔하다!

그럼 fast-forward 까지 진행하고 마무리 해보자.

회사에서 지금은 웹팀으로 옮겨서 SVN을 사용중이다. 물론 SVN이 심플해서 우리회사에는 더 어울리는 것 같다. 그래도 요새 대다수가 사용하는 git에 대해 항상 더 알고싶었는데 기회가 있어서 교육을 들어 좋았다.

계속해서 다양한 사례에서 rebase를 진행하는 걸 알아보자.

댓글()
  1. jun 2019.10.30 09:27 댓글주소  수정/삭제  댓글쓰기

    설명 깔끔하고 이해되기 쉬웠습니다!
    감사합니다 ㅎㅎ