최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday

티스토리 뷰

git merge와 git rebase의 차이점에 대해서 알아보고, 실무에서 어떻게 사용했는지 기록을 남긴다

 

지난글에 이어서 이번에는 git rebase에 대해서 정리해본다

 

git rebase 실습하기)

 

git rebase 실습을 위해서 일일이 구성물을 만드는게 번거로운 작업이 될 수 있다

 

따라서 실습을 위해서 git 환경을 터미널로 빠르게 구성해보고 학습하기로 한다

 

지금 이 글을 작성하는 개발환경은 `MacOS Ventura 13.3.1` 에서 `git version 2.39.0` 으로 수행하였다. (2023.10)

 

다음의 git merge step1 ~ step6 까지를 드래그하여 터미널에 복사-붙여넣기 하여 실습을 위한 환경을 구축할 수 있다

 

step을 나눈 이유는 몽땅 드래그해서 붙여넣으면 터미널에서 명령어 실행 속도에 따라서 브랜치 순서가 꼬일 수 있기 때문이다

 

step.01) rebase 저장소 생성후 main에서 첫 커밋

# rebase 라는 디렉토리를 생성하고 이동한다
mkdir rebase && cd rebase

# git 초기화 하며, 최초 브랜치는 main으로 설정한다
git init --initial-branch=main

# MAIN.md 라는 파일을 한개 만든다
touch MAIN.md

# 생성된 MAIN.md 파일을 `add` 명령어로 스테이징 영역에 추가하여 관리대상으로 등록시킨다
git add MAIN.md

# 변경 작업을 git 저장소에 기록한다
git commit -m "initialize commit"

 

step.02) develop 브랜치 만들고 커밋

# develop 브랜치 생성한다
git checkout -b develop

# develop.txt 파일 생성 후 커밋
touch develop.txt
git add develop.txt
git commit -m "created develop branch"

 

step.03) develop => featrue 브랜치 만들고 커밋

# feature 브랜치 생성
git checkout -b feature

# feature.txt 파일 생성하고 커밋
touch feature.txt
git add feature.txt
git commit -m "created feature branch"

 

step.04) develop => hotfix 브랜치 만들고 버그수정 작업을 하여 커밋

# develop 브랜치로 이동
git checkout develop

# develop 브랜치를 가지고 hotfix 브랜치를 생성한다
git checkout -b hotfix

# hotfix.txt 파일 생성 후 커밋
touch hotfix.txt
git add hotfix.txt
git commit -m "created hotfix branch"

# hotfix.txt 파일에 "bug fix"라는 텍스틑 입력한 작업을 수행한다 (실제 무언가의 작업을 했다는 이력을 나기기 위함)
echo "bug fix" >> hotfix.txt

# 작업된 hotfix.txt 파일을 커밋한다
git add hotfix.txt
git commit -m "bug fix"

 

step.05) develop => refactor 브랜치를 만들고 리팩토링 작업을 하여 커밋

# develop 브랜치로 이동
git checkout develop

# devleop 브랜치를 참조한 refactor 브랜치 생성
git checkout -b refactor

# refactor.txt 생성 후 커밋
touch refactor.txt
git add refactor.txt
git commit -m "refactoring work"

 

step.06) 여기까지 수행하고 이제 feature 브랜치로 돌아간다

git checkout feature

 

현 rebase 저장소의 전체 브랜치 상황은 다음과 같다

step.01) main 브랜치를 먼저 생성했으며

step.02) main 브랜치를 참조하여 develop 브랜치를 생성했다.

step.03 ~ step.05) 이후 develop 브랜치를 참조한 feature, hotfix, refactor 브랜치를 생성했다.

step.06) 이동된 feature 브랜치에서 그래프로 보면 아래와 같이 표시된다

 

(좌: vs code에 내장된 git graph의 모습 / 우: vs code 확장프로그램으로 Git Graph를 설치하여 보았을때 모습)

 

* 여기까지는 git merge와 상황이 완전히 일치한다

 

hotfix 브랜치를 feature 브랜치로 rebase)

git checkout hotfix
git rebase feature

 

merge와는 다르게(merge의 경우 먼저 feature브랜치로 이동했다면) 이번에는 hotfix 브랜치로 이동한 뒤

feature 브랜치로 rebase 한다

 

rebase를 사용했기 때문에 hotfix 브랜치의 커밋을 feature 브랜치 위로 올렸기 때문에

다음과 같이  hotfix에서 `main=>develop=>feature` 까지의 작업 내역이 모두 보이게 된다

 

그래프로 보면 다음과 같다

 

(git graph 확장팩 그래프는 다음과 같다)

 

refactor 브랜치를 hotfix 브랜치로 rebase)

 

전의 rebase와 방법은 동일하다

 

git checkout refactor
git rebase hotfix

 

refactor 브랜치로 이동하여 hotfix 브랜치를 rebase 한다

 

이제 refactor 브랜치에 hotfix 작업내역이 보인다

 

그래프로는 다음과 같다 

 

(git graph 확장팩 그래프는 다음과 같다)

 

refactor 브랜치에서 develop으로 rebase 하기)

이제 마지막 rebase이다

 

develop에는 다음과 같이 develop에 대한 작업밖에 없지만

 

rebase 병합을 통하여 아래와 같이 변경될 것이다

git checkout refactor
git rebase develop

 

최종 develop 브랜치로 이동해서 살펴보자

git checkout develop

 

모든 작업내역이 다 병합되었고

 

작업 이력이 main => feature => hotfix => refactor => develop 까지 한줄로 표시되었다

 

(git graph 확장팩 그래프는 다음과 같다)

 

이렇게 rebase를 통해 커밋 히스토리를 변경하였기 때문에 merge보다 깔끔한 커밋 히스토리를 유지할 수 있게 되었다

 

충돌을 피하기 위한 최선의 방법)

 

rebase, merge 모두 동일한 파일에서 작업하는 경우 충돌을 피할 수 없다.

 

따라서 가장 좋은 방법은 `작업전 동기화` 하는 방법이 가장 최선이라고 할 수 있다

 

병합 취소할 때는 git reset 혹은 git revert)

병합 취소는 크게 두가지가 있다.

 

git reset --hard <커밋id> 이후, git push -f origin

 

git revert <커밋id> 이후, git push

 

하는 방법이 있는데, 개인적으로 회사나 팀단위로 작업하는 경우엔 `git revert`를 추천한다

 

`git reset --hard`의 경우 커밋 히스토리 자체가 삭제되기 때문에, 로컬에서 이 명령어로 reset 한뒤

 

작업을 하고 원격 저장소에 push 하는 경우, 원격에서는 아직 reset으로 삭제 되지 않은 커밋이 남아있기 때문에

 

충돌이 발생한다.

 

그래서 그 충돌을 피할 수 있는 옵션으로 `-f` 를 사용하여 `git push -f origin`으로 강제 푸시를 할 수 밖에 없는데

 

요새는 그리 권장하지 않는 방법이기도 하고, 대부분의 경우 git 저장소에 권한이 없을 경우가 많아 강제푸시가 안될 것이다.

 

반면에 git revert의 경우 커밋은 남겨 둔채로 새로이 되돌려진 커밋을 생성하기 때문에 충돌이 발생하지 않는다

 

 

 

 

댓글