2023. 3. 6. 00:14ㆍTools/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 merge
와no 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(가장 앞에)에 있을 때 사용한다.
→ merge
는 ff
와 no-ff
방식이 존재하고 rebase
는 ff
할 필요가 있다.
실제로 fetch
와 merge
를 활용해서 conflict를 해결하는 방법을 배워보자.
이건 꼼지락거리다가 vscode에서 찾은 내 working tree다.
요기 누르면 된다.
출처 : https://backlog.com/git-tutorial/kr/stepup/stepup1_4.html
2. merge
기본적으로 충돌이 일어난 부분은 이렇게 일일이 확인해서 수정해 주어야 합니다.
일단 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
상황은 아직 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를 해보자.
사실 앞에서는 merge
와 rebase
를 수행하는 방법에 대해서 알아보았다.
어떻게 충돌을 해결하면 좋을진 아직 모르겠다.
충돌이 발생하는 부분은 모두 일일이 확인해서 수정해야 한다.
일단 어디에서 왜 충돌이 발생하는지 알아낸다.
가. 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
다.
가능하다면 fetch
와 merge
를 활용해서 차근차근 conflict를 해결하는 방법을 사용하자.
출처 : https://www.atlassian.com/ko/git/tutorials/syncing/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 |