본문 바로가기
DevOps/Git

Git - Rebase 개념과 충돌처리 과정 정리

by 맑은안개 2021. 8. 23.

Rebase

다음은 rebase 명령을 이해하기 위해 임의로 생성한 branch 들이다.

rebase짧은 주기를 갖는 관련있는 브랜치들끼리의 history를 간결화 하는데 유용하게 사용된다.

한 조상에서 나온 clientserver 브랜치를 살펴보자.

client 브랜치를 master 브랜치와 병합하기 위해 rebase 명령을 사용해보자.

$git checkout client
$git rebase master

VSCode 의 Git history상에는 변경사항이 없지만 실제 일어나는 일을 설명하면 두 브랜치가 나뉘기 전인 공통 커밋으로 이동하고, 그 커밋부터 지금 checkout한 브랜치가 가리키는 커밋까지 diff를 차례로 만들어 임시저장한다. 이 때 충돌이 있다면 충돌을 처리해야 한다. ( 처리하는 방법은 뒤에서 알아보자)

Rebase할 브랜치(client) 가 합칠 브랜치(master) 가 가리키는 커밋을 가리키게 하고 아까 저장해 놓았던 변경사항을 차례대로 적용한다.

https://git-scm.com/book/ko/v2/Git-브랜치-Rebase-하기

$git checkout master
$git merge client
Updating c6d359a..b8e0a3e
Fast-forward
 src/Components/Client.js | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 src/Components/Client.js

Fast-forward 메세지로 우리는 해당 커밋이 충돌없이 merge된 것을 확인할 수 있다.

rebase로 server, server-2에서 발생하는 충돌 처리

이제 server 브랜치와 server-2 브랜치를 rebase 한다. 동일한 코드를 수정하였으므로 충돌(conflict)이 발생할 것이다.

📃Server.js from server branch

export default function Server() {
  const server_2 = "Added special variables";

  return <>This is server</>;
}

📃Server.js from server-2 branch

export default function Server() {
  const server_2 = "added server-2 var";

  return <>This is server</>;
}
$git checkout server-2
$git rebase server
error: could not apply e3ebbbb... added var for server-2
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply e3ebbbb... added var for server-2
Auto-merging src/Components/Server.js
CONFLICT (content): Merge conflict in src/Components/Server.js

위 명령을 실행하면 충돌이 일어나고 해당 메세지를 출력한다.

이 때, 충돌하기 전으로 돌리고 싶다면 --abort 명령을 사용할 수 있다.

$git rebase --abort

코드 실행 시 충돌이 발생한 Server.js 도 원래대로 돌아간다.

이제 다시 rebase 하여 충돌을 처리 해보자.

$git difftool
diff --cc src/Components/Server.js
index 7ea2df3,eaa72c0..0000000
--- a/src/Components/Server.js
+++ b/src/Components/Server.js
@@@ -1,5 -1,5 +1,9 @@@
  export default function Server() {
++<<<<<<< HEAD
 +  const server_2 = "Added special variables";
++=======
+   const server_2 = "added server-2 var";
++>>>>>>> e3ebbbb (added var for server-2)

    return <>This is server</>;
  }

mergetool

$git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
tortoisemerge emerge vimdiff nvimdiff
Merging:
src/Components/Server.js

Normal merge conflict for 'src/Components/Server.js':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (vimdiff):

mergetool 명령은 충돌을 처리하기 위한 GUI를 실행한다.

본 예에서는 vimdiff 를 실행하였으나 meld, opendiff , tortoisemerge 등 다른 mergetool을 설치하여 사용할 수 있다. 다른 mergetool을 사용하기 위해 git config 옵션중 merge.tool 옵션을 사용하여 변경 할 수 있다.

git mergetool 사용후 VSCode

📃vimdiff

vim 기반에 diff tool인 vimdiff의 모습이다.

충돌을 처리(merge)하고 난 후의 모습

변경 내용을 저장하고 나면, Server.js.orig 파일이 생성된다. orig 파일은 merge후 생기는 충돌당시의 내용을 기록한 백업파일인데 여기선 커밋할 필요가 없으니 해당 파일을 지우고, 충돌처리한 Server.js 를 commit 처리한다.

  • orig 옵션 끄기
  • git config --global mergetool.keepBackup false
λ git branch
* (no branch, rebasing server-2)
  client
  master
  server
  server-2

위에서 mergetool을 사용해 변경을 하고 commit을 안한 상태에서 git branch를 실행하면 아직 Rebasing 하고 있는 것을 확인할 수 있다.

이 상태에서 git checkout을 하게 되면 --continue , --abort , --skip 을 사용하여 직전에 Rebase했던 작업을 처리해야 한다.

Rebasing 마무리하기

$git rebase --continue
Successfully rebased and updated refs/heads/server-2.

$git branch
  client
  master
  server
* server-2

--continue 명령으로 rebase 작업을 계속 이어나간다. 더 이상 충돌처리 할게 없다면 원 브랜치로 이동된다.

이제 server-2 브랜치는 server 브랜치에서 작업한 내용을 rebase하여 history상 깔끔하게 정렬되었다. server 브랜치를 삭제하여 작업을 마무리 한다.

$git branch -d server
Deleted branch server (was 66a8c9f).

반응형