[Github] conflict 해결하기

2023. 3. 6. 00:14Tools/GitHub

 

로컬에서 작업을 하다가 pull을 할 때 conflict가 발생한다.

 

원격 저장소의 변경사항과 로컬 저장소의 변경사항 사이에 누구를 우선적으로 반영할지 판단하기 어려워서 발생한 것 같다.

 

conflict를 해결해보자.

 


1. conflict 발생

 

늘 하던 대로 pull 했더니 다음과 같이 문제가 생겼다.

 

❯ git pull origin mysql
https://github.com/ramen4598/Study_nodeJS URL에서
 * branch            mysql      -> FETCH_HEAD
힌트: You have divergent branches and need to specify how to reconcile them.
힌트: You can do so by running one of the following commands sometime before
힌트: your next pull:
힌트:
힌트:   git config pull.rebase false  # merge
힌트:   git config pull.rebase true   # rebase
힌트:   git config pull.ff only       # fast-forward only
힌트:
힌트: You can replace "git config" with "git config --global" to set a default
힌트: preference for all repositories. You can also pass --rebase, --no-rebase,
힌트: or --ff-only on the command line to override the configured default per
힌트: invocation.
fatal: Need to specify how to reconcile divergent branches.

 

 

 

만약 bugfix를 위해서 새로운 branch를 만들어서 작업했다고 가정하자.

 

이제 작업을 마치고 master branch에 반영하려고 한다.

 

merge, rebase, fast-forward가 뭐 하는 건지 이해해 보자.

 

 

 

 

  • merge : fast-forward mergeno fast-forward merge로 나뉜다.

 

  • no fast-forward merge : : 충돌을 어떻게든 해결하고 두 branch를 통합해서 새로운 master branch commit을 생성한다.

 

  • rebase : bugfix branch의 이력이 master branch를 앞선다.

 

  • fast-forward : rebase만 하면 아래 그림에서와 같이, master의 위치는 그대로 유지된다. master branch의 위치를 변경하기 위해서는 master branch에서 bugfix branch를 fast-foward(빨리감기) 병합하면 된다. 통합할 branch 즉 bugfix branch가 이미 HEAD(가장 앞에)에 있을 때 사용한다.

 

mergeffno-ff 방식이 존재하고 rebaseff할 필요가 있다.

 

 

실제로 fetchmerge를 활용해서 conflict를 해결하는 방법을 배워보자.

 

이건 꼼지락거리다가 vscode에서 찾은 내 working tree다.

 

 

요기 누르면 된다.

 

출처 : https://backlog.com/git-tutorial/kr/stepup/stepup1_4.html


2. merge

 

기본적으로 충돌이 일어난 부분은 이렇게 일일이 확인해서 수정해 주어야 합니다.

 

 

누구나 쉽게 이해할 수 있는 Git 입문~버전 관리를 완벽하게 이용해보자~ | Backlog

누구나 쉽게 알 수 있는 Git에 입문하신 것을 환영합니다. Git을 사용해 버전 관리를 할 수 있도록 함께 공부해봅시다!

backlog.com

 

일단 master, issue2, issue3 branch가 존재한다 가정한다.

 


가. fast-forward merge

 

issue2 branch는 master branch에서 myfile.txt라는 파일에 내용을 추가했다.

$ git checkout master
Switched to branch 'master'

$ git merge issue2
Updating b2b23c4..8f7aa27
Fast-forward ---------------------------> 여기!
 myfile.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

 

 


나. no-ff merge

 

issue2를 병합하면서 master branch는 issue3를 생성한 이후에 변화가 생겼다.

 

이제 issue3를 병합하려고 한다면 conflict가 발생한다.

 

누구의 변화를 적용해서 하나의 master를 만들지 고민해야 한다.

 

$git merge issue3
Auto-merging myfile.txt
CONFLICT (content): Merge conflict in myfile.txt
Automatic merge failed; fix conflicts and then commit the result.

충돌 부분을 모두 수정하고 다시 커밋한다.

 

# On branch master
$ git add myfile.txt
$ git commit -m "issue3 브랜치 병합"
nothing to commit (working directory clean)
  • git merge --abort : merge 자체를 취소하고 싶으면 사용

 

 

병합되면서 master branch에 새로운 commit을 생성했다.

 


3. rebase

 

 

누구나 쉽게 이해할 수 있는 Git 입문~버전 관리를 완벽하게 이용해보자~ | Backlog

누구나 쉽게 알 수 있는 Git에 입문하신 것을 환영합니다. Git을 사용해 버전 관리를 할 수 있도록 함께 공부해봅시다!

backlog.com

 

상황은 아직 issue3가 병합되기 전을 가정한다.

 

 

$ git checkout issue3
Switched to branch 'issue3'

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: pull 설명을 추가
Using index info to reconstruct a base tree...
<stdin>:13: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging myfile.txt
CONFLICT (content): Merge conflict in myfile.txt
Failed to merge in the changes.
Patch failed at 0001 pull 설명을 추가

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".

우리가 issue3를 merge할 때는 conflict를 해결하고 새로 commit했었다.

 

하지만 rebase의 경우 충돌 부분을 수정한 후 commit 이 아니라 rebase 명령에 --continue 옵션을 지정하여 실행해야 한다.

 

$ git add myfile.txt
$ git rebase --continue
  • --abort : rebase 자체를 취소하고 싶으면 사용

 

 

아직 master branch는 저 뒤에 있다.

 

이제 master로 전환해서 issue3의 변경 사항을 모두 ff-merge한다.

 

$ git checkout master
Switched to branch 'master'

$ git merge issue3
Updating 8f7aa27..96a0ff0
Fast-forward
 myfile.txt |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

 

 


4. fetch, diff를 해보자.

 

사실 앞에서는 mergerebase를 수행하는 방법에 대해서 알아보았다.

 

어떻게 충돌을 해결하면 좋을진 아직 모르겠다.

 

충돌이 발생하는 부분은 모두 일일이 확인해서 수정해야 한다.

 

일단 어디에서 왜 충돌이 발생하는지 알아낸다.

 


가. fetch

 

원격 저장소에서 코드를 내려받는다.

 

단, 내려받은 후 현재 브랜치와 병합하진 않는다.

 

git fetch origin <branch>

이때 원격 저장소에서 커밋된 코드는 임시 branch (일명 FETCH_HEAD) 형태로 로컬에 존재한다.

 

git checkout FETCH_HEAD

FETCH_HEAD의 이름으로 체크아웃할 수도 있다.

 


나. diff

 

git diff <branch>

로컬 저장소의 브랜치와 원격 저장소 브랜치 사이의 어떤 차이점을 확인한다.

 

git diff <branch1> <branch2>

혹은 서로 다른 branch를 비교하고 싶다면 이렇게 사용한다.

 


다. fetch → diff → merge의 삼단콤보

 

git fetch origin <branch>
git diff FETCH_HEAD <branch>

원격 저장소와 로컬 저장소의 차이를 확인할 수 있다.

 

 

git checkout <branch>
git merge FETCH_HEAD

나중에 push 할 때를 생각해서 FETCH_HEAD에서 작업하면 안 된다!

 

❯ git merge FETCH_HEAD
자동 병합: gitconflict.txt
충돌 (추가/추가): gitconflict.txt에 병합 충돌
자동 병합이 실패했습니다. 충돌을 바로잡고 결과물을 커밋하십시오.

gitconflict.txt에서 충돌이 발생했다.

 

vim gitconflict.txt

그냥 충돌이 발생한 파일을 vim으로 열었는데 바로 충돌 부분을 확인할 수 있다.

 

  • <<<<<< HEAD ~ : 지금 checkout하고 있는 FETCH_HEAD의 코드
  • ======== : 기준점
  • ~ >>>>>>> : merge할 FETCH_HEAD branch의 코드

 

수정하기 위해서는 보이는 기호를 포함해서 필요 없는 모든 것은 지우고, 필요한 것은 추가해서 저장하면 된다.

 

수정이 완료했으면 새로 commit한다.

 

# 주의 mysql branch에서 수행
$ git add .
$ git commit -m "브랜치 병합"
$ git push origin mysql

 


5. pull vs merge

 

결국 git pull = git fetch + git merge다.

 

가능하다면 fetchmerge를 활용해서 차근차근 conflict를 해결하는 방법을 사용하자.

 


출처 : https://www.atlassian.com/ko/git/tutorials/syncing/git-fetch

출처 : https://git-scm.com/docs/git-fetch

'Tools > GitHub' 카테고리의 다른 글

[Github] Git flow  (0) 2023.04.11
[Github] 대용량 파일 공유  (0) 2023.03.17
[Github] issue  (0) 2023.02.27
[Github] action  (0) 2023.02.27
[Git] git ignore  (0) 2023.02.12