호댕의 iOS 개발

[Git] rebase를 자세히 알아보자 (개념, 사용법, 강제 푸쉬 등에 관하여) 본문

Software Engineering

[Git] rebase를 자세히 알아보자 (개념, 사용법, 강제 푸쉬 등에 관하여)

호르댕댕댕 2022. 8. 9. 22:02

이전 글에서 간단하게 rebase를 사용하여 이미 push한 commit의 내용을 바꾸는 방법을 포스팅한 적이 있다. 

 

[Git] 이미 Push를 해버린 Commit을 어떻게 고치지...

이미 커밋을 하고 한~참 시간이 지났다가 중간에 딱 한 커밋이 카르마 규칙을 준수하고 있지 않은 것을 발견했다. 지금까지 바로 직전의 커밋이었으면 reset을 하고 다시 커밋을 했지만 이미 다

ho8487.tistory.com

다만 그 당시 이해했던 rebase는 아직 rebase의 본 기능을 제대로 사용하지 못했었다. 

 

단지 Commit 메세지를 수정할 방법을 찾다가 단순히 rebase를 알게 된 것이었다. 

 

실제 현업에 근무하게 되면서 협업을 할 때 rebase는 거의 필수로 사용해야 하는 기능이라는 것을 알 수 있었다. 그래서 내가 이해했던 내용들을 바탕으로 rebase를 다시 정리해보고자 한다. 

 

rebase의 개념

rebase는 이름 그대로 base를 다시 맞춘다는 것이다. 

만약 아래 그림처럼 특정 브랜치 A에서 다른 브랜치 B를 파서 작업을 하고 있었는데 A 브랜치에 다른 사람이 추가로 커밋을 올리는 상황을 생각해보자.

이렇게 되면 merge를 하려고 하면 Conflict이 나게 된다. 이는 Github에서도 친절하게 알려준다. 

그 이유는 이미 특정 브랜치 A에는 추가적인 commit이 올라간 상황인데 다른 브랜치 B에서는 추가된 커밋이 없이 브랜치 B에서 쌓은 커밋만 존재하기 때문이다. 

 

브랜치 A에는 이미 1 - 2 - 3 - 4 커밋이 쌓여있고 브랜치 B의 로그를 보면 1 - 2 - 1 - 2로 쌓여있을 것이다. 그런데  1 - 2 - 3 - 커밋이 쌓인 브랜치에 머지를 하려고 하니 당연히 컨플릭이 발생하게 되는 것이다. 

 

그래서 사용할 수 있는 것이 바로 rebase이다. 

rebase를 하게 되면 특정 브랜치 A의 Head에 맞춰 그 뒤로 브랜치 B에서 쌓은 커밋들이 쌓이게 된다. 

브랜치 B의 커밋이 달라지게 된다

하지만 이렇게 되면 문제가 발생한다. 

 

기존 브랜치 B에서 쌓은 커밋들을 그대로 브랜치 A의 최신 커밋 위에 쌓은 것처럼 보이지만 확인해보면 브랜치 B에서 쌓은 커밋들의 해시값들이 변경되 있는 것을 확인할 수 있을 것이다. 

(해시값은 git log 명령어를 통해 쉽게 확인할 수 있다)

 

그래서 만약 이미 리모트(github)에 푸쉬를 한 상황이라면 로컬과 리모트의 상태가 달라지게 된다. 

그래서 이때 git push -f를 통해 강제 푸쉬를 해줘야 한다. 그런데 아마 많은 블로그들이나 나 또한 강제 푸쉬는 협업을 할 때 절대 쓰면 안된다고 하고 있다. 

 

왜 강제 푸쉬가 위험한 것일까?

다른 곳에서도 말하는 것처럼 강제 푸쉬는 위험하긴 하다. 바뀐 커밋을 강제로 리모트에 올려버리는 것이기 때문에 만약 다른 사람들과 같이 작업하고 있는 브랜치에 강제 푸쉬를 하게 되면 리모트에서도 전부 커밋의 해시값이 바뀌게 되면서 다른 사람들의 작업물에도 영향을 주게 된다. 이렇게 되면 엄청나게 꼬여버릴 수 있게 되는 것이다. 

 

그래서 강제 푸쉬를 조심해서 쓰라고 하는 것이다. 

 

하지만 조심해서 사용해야지 아예 쓰지 말라는 것은 아니다

불가피하게 강제 푸쉬를 통해 리모트의 상태를 변경해줘야 하는 경우도 있었다. (필요한 경우엔 반드시 써야 한다)

 

대부분 git branch 전략을 가지고 있다면 feature 별로 브랜치를 따로 파서 작업을 하고 이를 development 브랜치에 머지하는 식으로 작업을 할 것이다. 

우아한 형제들 git flow를 봐도 유사한 형태이고 말이다. 

 

우린 Git-flow를 사용하고 있어요 | 우아한형제들 기술블로그

{{item.name}} 안녕하세요. 우아한형제들 배민프론트개발팀에서 안드로이드 앱 개발을 하고 있는 나동호입니다. 오늘은 저희 안드로이드 파트에서 사용하고 있는 Git 브랜치 전략을 소개하려고 합

techblog.woowahan.com

 

그렇다면 보통 feature별로 판 브랜치는 1~2명 정도만 사용하게 될 것이다. 

 

2명일 때는 좀 더 조심해야겠지만 1명이서 특정 브랜치에서 작업을 하는 경우 강제 푸쉬를 한다고 해서 크게 문제가 생기지 않는다. 

오히려 rebase를 하지 않고 기존 development 브랜치로 머지를 하려한다면 문제가 생길 것이다. 

 

2명 이상이서 작업을 하던 브랜치를 reset하는 등 변경 할 때에는 일단 git branch -D {branch 이름} 명령어를 사용해 기존 브랜치를 지운 다음 다시 git switch {지웠던 branch}로 이동해 remote와 상태를 동일하게 만드는 방식을 사용했다.

 

물론 다른 사람들이 작업하고 있는 branch를 이렇게 해버린다면 돌이킬 수 없을 수도...

(지우고 다시 돌리면 기존 작업물들이 다 날라가기 때문이다)

 

rebase를 사용해보자

rebase를 사용하는 것은 생각보다 간단하다.

 

일단 rebase가 필요한 상황은 작업을 하기 위해 만들었던 브랜치의 root branch에 추가로 커밋이 생겼을 때이다. 

그렇다면 일단 local의 root branch도 최신화를 해줘야 한다. 

 

따라서 다음과 같은 과정을 통해 작업을 해줘야 한다. 

1. git switch {최신화를 해줘야 하는 branch}를 통해 해당 브랜치로 이동 

2. git pull 을 통해 최신화를 해준다. 

 

이렇게 했다면 일단 최신화가 필요한 root branch는 remote와 동일한 최신 상태가 됐다. 

 

그렇다면 이제 리베이스를 해줘야 한다. 

 

1. git switch {작업하고 있던 branch} 를 통해 리베이스가 필요한 브랜치로 돌아온다. 

2. git rebase {최신화를 해준 root branch} 를 통해 기존에 브랜치를 만들었던 지점이 아닌 가장 최근 커밋을 기준으로 다시 base를 맞추게 된다.

 

이렇게 하게 되면 작업하고 있는 브랜치에도 최신화를 해준 root branch의 커밋이 들어오게 되면서 Conflict이 발생하지 않게 된다. 

 

만약 커밋 내용을 수정하고 싶다면 git rebase -i  {최신화를 해준 root branch}를 통해 해주면 된다.

force push를 사용해야 하고 생각보다 겁을 먹었는데 생각보다 간단한 것 같다. 

 

하지만 이렇게 간단하기만 하면 rebase가 어려울리가 없지... 만약 rebase를 하면서 가져온 커밋과 현재 작성한 코드에서 중복으로 수정한 부분이 있다면 Conflict이 나게 된다. 

 

이런 Conflict은 어떻게 해결할 수 있을까?

 

Rebase를 하면서 Conflict 해결하는 방법 

Conflict이 난 것은 간단하게 iterm2만 봐도 알 수 있다. 

브랜치 주소가 딱봐도 자기 문제 있다는걸 티를 낸다. 

무슨 요상한 브랜치 이름으로 되어 있다. 그럼 Conflict이 발생한 것이다. 이를 해결해보자. 

 

일단 어디서 Conflict이 났는지 파악을 해야 한다. 

git status를 통해 보면 어디서 Conflict이 났는지 친절하게 알려준다. 

Unmerged paths라는 이름으로 알려주고 있다. 이유까지 both modified라고 알려준다. 즉, 동일한 곳을 2번 수정했다는 것이다. 

 

그럼 해당 경로로 가서 conflict가 난 부분을 확인하면 된다. 

빠르게 터미널로 가는 방법은 다음 명령어를 입력하면 된다. 

open -a Xcode {iterm에서 알려준 파일명}

그러면 해당 파일이 열리게 되고 여기서 <<(이렇게 코드에 표시가 된다) 를 검색해서 어느 부분이 conflict이 났는지 파악하고 수정해주면 된다. 

 

수정한 내용을 git add .를 통해 다시 stage area로 올려주고 git rebase --continue를 해주면 된다. 만약 또 Conflict이 난다면 다시 이 과정을 반복해서 해주면 된다. 

 

이렇게 하게 되면 리모트와 또 커밋 로그가 다르기 때문에 강제 푸쉬로 리모트에 이를 다시 반영시켜주면 된다! 

 


지금까지 리베이스란 뭔지, 언제 사용하는 것인지, 어떻게 사용하는 것인지, 문제가 발생하는 경우 어떻게 해결하면 좋은지에 대해 살펴봤다. 

 

리베이스를 제대로 활용해본 경험은 거의 처음이라 처음 사용했을 때는 부담도 됐는데 역시 직접 해보는게 가장 이해도 잘 되고 좋은 것 같다. 혹시 다른 분들도 rebase가 막막하시다면 직접 해보시는게 가장 빠른 길인 것 같습니다! 

Comments