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 저장소 Fork 후 Pull Request 및 최신 내용 갱신 방법

IT 지식/Git|2018. 10. 4. 00:34

이전직장에서도 SVN을 사용했다. 물론 GtitLab을 1년반정도 사용했으나 아쉽게도 협업하여 진행하지를 않아서 모두 master에 직접 커밋을 하였다.

그래서 이번에는 협업한다고 생각하고 시나리오를 만들어서 테스트를 진행해보자.

Github 저장소에서 상대방 Repository를 Fork하고 Pull Request를 요청해보고 변경된 최신내용을 Local에 반영하는 작업을 진행해보자.

1. 우선 Repository를 Fork 한다.


fork를 진행할 계정을 선택하고 확인을 누르면 내 Repository에 Fork된 저장소가 보이는 것을 확인할 수 있다.


2. SourceTree에 추가

Git을 Command를 사용해서 멋지게 사용하면 좋지만 실력이 부족하기 때문에 SourceTree를 사용해서 진행해보자.
SourceTree에 방금 Fork 했던 저장소를 추가해보자.


3. 소스코드 변경

Clone을 받은 코드를 내가 원했던 내용대로 수정하고 커밋과 push를 진행한다.


작업을 완료한 후 내 저장소에 가보면 정상적으로 커밋과 푸시가 완료된것을 확인 할 수 있다.


4. 변경사항 Pull Request
지금까지 진행한 내용은 내 개인 Repository에만 반영되어있다. 실제로 원래 저장소에 가보면 원래 상태 그대로인것을 확인할 수 있다.

그럼 위에 그림에서 New pull request 버튼을 누르고 비교할 브랜치를 선택 해준다.

그러면 아래와 같이 변경사항과 함께 Pull request를 만들 수 있는 화면이 나온다

그럼 코멘트를 작성하고 Pull Request를 만들어보자.

요청이 완료되었고  이제 저장소의 원래 소유자가 요청을 받아주면 작업을 완료 할 수 있습니다.


5. Pull Request 수락.

원래 Repository의 주인인 dauns 계정으로 들어가 보면 Pull Request가 하나 있는것을 확인할 수 있다.
여기서 이 요청을 거절할 수도 있고, merge 할수도 있고 rebase 할수도 있다.

테스트이기 때문에 Merge 해보자.

Merge를 하고 나면 저장소에 내용이 변경되었고 Pull Request도 사라진것을 확인할 수 있다.

6. 원격 저장소 변경사항 Local에 반영

내가 fork를 진행한 원격 저장소 내용이 변경되어서 내가 fork를 진행한 저장소와 달라졌다고 가정해보자. 

위에 그림에 보면 tt.java라는 파일이 추가되었고 내 저장소에는 저 내용이 반영되어 있지 않다.

이를 반영하기 위해서는 먼저 원래 저장소를 upstream의 이름으로 원격저장소로 추가해줍니다.


그리고 추가된 upstream에서 우측클릭을 한 후  "upstream에서 가져와 병합하기"를 선택합니다.

그러면 원격저장소의 내용이 내 Local Repository에 반영이 되었습니다. 


이 내용을 commit & push 하여 내 원격 저장소에도 반영을 해주면 완료됩니다.

확실히 GIT이 더 어렵다. 

지금이야 간단하지 꼬이면 참 귀찮아질 것 같다. 사례를 많이 만들어봐서 연습해봐야겠다.

댓글()

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를 이용한 커밋 정리 (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 댓글주소  수정/삭제  댓글쓰기

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