본문 바로가기
DevOps/Linux, Git

[Git] Git Merge 두가지 방식(Fast-Forward, 3-way)

by DUSTIN KANG 2023. 12. 3.

지난 포스팅에서는 해당 브랜치를 앞서 커밋한 브랜치와 병합하기 위해 `git merge 대상 브랜치` 명령어에 대해 알아보았다.

이번 포스팅에는  Merge와 연관된 두가지 방식과 Rebase에 대해 알아보려고 한다.

Merge와 연관된 두가지 방식

Fast-Forward

Fast-Forward(⏩) 방식은 과거 커밋한 내역을 수정을 하여 포인터만 최신 커밋을 이동하는 방식을 말한다. 어차피 브랜치끼리는 시작점이 동일하기 때문에 단순하게 병합할 수 있는 방식이다.

다음 예시를 보자.

 

main 브랜치에서 ex.py라는 파일을 만들고 Feature/job#1이라는 브랜치를 생성하여 b.py 라는 파일을 생성했다.

그리고 나서, main 브랜치에서 Merge를 시도했다. 이처럼 단순히 최신 커밋으로 포인터를 이동하는 방식을 Fast-Forward라고 합니다.

 

fast-forward

3-way merge

혼자의 경우보다 협업에 많이 발생하는 merge 방식으로 다음과 같은 상황이 예시이다.

왼쪽 그림을 보자.

Main 브랜치에서 먼저 Feature/job#2이라는 브랜치를 생성하고 Add c.py라는 작업을 진행했다.(커밋까지)

이후, Feature/job#1 브랜치에서 생성했었던 B를 고치는 Fix b.py라는 작업을 수행했다.(여기도 커밋까지)

job#2보다 먼저 job#1를 merge했고 먼저 파일을 생성했지만 뒤늦게 main 브랜치에서 job#2를 Merge했다고 가정하자.

 

3-way merge

 

이러한 상황에서 3-way Merge가 발생한다.

그리고 Merge를 진행하면 3-way를 문구는 뜨지 않고 머지가 되었음을 말해준다. 

 

`tig`와 log를 보고 확인해본 결과, 커밋 시점이 더 빠른 Feature/job#2 작업이 먼저 수행되고 그 다음에 job#1의 작업이 수행된 것으로 확인할 수 있다. 만약 중복된 줄에 코드가 변경된다면, 충돌도 발생할 수 있기 마련이다.

 

 

Rebase

Base를 다시 지정한다는 명령어이다. 브랜치 생성 기준을 다시 재지정한다는 얘기다.

rebase는 merge 시점에 기준 Branch의 가장 최신 커밋 시점으로 base를 변경해 fast-forward하게끔 병합하는 방법이다.

  • 물론, Rebase 도중, 동일부분에 수정이 있다면 충돌이 일어난다. 이럴 땐, 충돌을 정리하고 rebase를 해줘야 한다.
  • `git rebase -i main`을 하면 main브랜치의 시점을 rebase하는데 대화형 모드를 통해 변경하게끔 한다.

다음 예제를 보자.

Main 브랜치에서 Feature/job#1에서 rebase.md라는 파일을 추가하고 커밋하고 수정하고 커밋했다고 하자.

그다음에 Main 브랜치에서 ex.py를 수정했다. 이때, Rebase를 통해 시점의 기준을 `Modify ex.py`로 변경할 수 있다.

그러면, 자연스럽게 Fast-Forward 할 수 있다. 만약, 충돌이 일어난다면 충돌을 수정해줘야 한다.

 

좌) rebase 이전, 우) rebase 이후

 

위 오른쪽 그림과 같이 `rebase -i BRANCH`를 통해 rebase를 적용하고 나면 아래 처럼 성공적으로 Rebase가 완료되었다고 뜬다.

 

 

rebase -i

 

그러나 아래 그림처럼 충돌이 발생하는 경우도 있다. 중복된 위치를 수정하는 경우이다.

 

log

깃 로그(log)는 커밋의 히스토리를 보여주는 명령어이다.

로그를 사용하는 옵션으로 대표적인 4가지가 있다.

  • git log -p : 각 커밋마다 변경사항을 함께 보는 방법 (무엇이 추가(+)되었고 무엇이 지워(-)졌는지 확인할 수 있다.)
  • git log -숫자 : 최근 부터 커밋을 몇개까지 볼 건지 하는 옵션이다.
  • git log --stat : 통계 옵션으로 해당 커밋의 점유율을 확인할 수 있다.
  • git log --oneline : 한줄로 간단하게 요약해서 보여줄 수 있는 방법이다.
  • git log --oneline --graph : 그래프로 보여줄 수 있다. `tig`를 사용하는 게 더 편하면 tig를 사용해도 된다.
  • git log -S "검색어" : 변경 사항 내 단어를 검색할 수 있다.
  • git log -grep "검색어" : 커밋 메세지 내 검색을 할 수 있다.

 

git log

 

git diff

`modified` 상태 일 때, 파일의 변경 차이를 확인할 수 있는 명령어이다.

 

git reflog

그동안의 모든 작업을 확인할 수 있는 명령어이다.

`git log`로는 확인할 수 없었던 로그들을 `git reflog`라는 명령어로 모든 내역을 확인해볼 수 있다. 

만약 작업을 되돌리고 싶으면 regflog에서 커밋 넘버를 복사하고 `git reset --hard 커밋넘버 하면 된다.

 

git reflog

 

git blame

누가 어느 코드에 작업을 했는지 책임소재를 분명히하기 위해 사용되는 명령어이다. 원인을 파악하기 위해 사용된다.

`git blame 파일명` 혹은 `git blame -L {코드라인넘버} {파일명}`으로 특정 코드라인에 대해 확인할 수 있다.

 

git blame -L 7,8 code.py
# code.py의 7,8 라인 확인

git blame

 

git summary

해당 프로젝트의 기여율을 확인할 수 있는 명령어이다.

이전에 `brew install git-extras`를 설치해야 한다.

 

git summary

 

💡 VS Code 플러그인으로 `git lens`를 설치하는 방법이 있다.
git lems는 해당 라인의 blame을 확인해줄 수 있는 플러그인이다.