[Git] Remote 저장소로 부터 merge conflict시에 rebase 명령 사용하기
Remote 저장소인 GitHub과 Local 저장소의 commit 내역이 일치하지 않을 경우 rebase로 어떻게 해결하는지 알아보자. Local 저장소내에서 rebase를 사용하는 것과 약간의 차이점이 존재한다. (참조)
1. Remote 저장소 merge conflict 조건
- GitHub에 이미 다른 Commit이 존재한다 (분홍색)
- Local 저장소에 변경된 commit이 존재한다
- git push 를 수행할 경우 merge conflict가 발생한다
- 기존에 push후 conflict 발생시 pull 하고 문제 해결하고 다시 push 한다 (해결하기)
2. 이제 1)번의 경우 말고 fetch 와 rebase 사용
- git fetch 를 통하여 local 저장소로 merge 하지 않고 origin/master의 별도 브랜치를 local 저장소로 복사하자
- git rebase를 수행한다. 이때 다음의 3단계로 진행이 된다.
+ 브랜칭 된 이후의 master commit 내역을 temporary area로 이동시킨다-origin/master가 아니라- (초록색)
+ origin/master를 master 브랜치로 commit 한다. (분홍색)
+ temporary area에 있는 master commit 내역을 다시 master로 commit 한다.
3. local과 remote의 같은 파일을 commit 하였을 때 rebase 하는 방법
- master 브랜치에서 rebase하고 있음에 주의한다
////////////////////////////////////////////////////////////////////////////
// remote 저장소와 commit 내역을 맞추고 확인해 보자
$ git log --pretty=oneline
bbeb691d80512e17279764312f60416ebf28dd86 add content in rebase of local repo
// rebase.html 파일의 내용
////////////////////////////////////////////////////////////////////////////
// 로컬에서도 rebase.html 파일을 변경하고 push를 시도하지만 reject 된다.
// 즉, remote 저장소의 rebase.html과 local 저장소의 rebase.html 내역이 틀리다.
$ git push
Username for 'https://github.com':
Password for 'https://ysyun@yuwin.co.kr@github.com':
To https://github.com/ysyun/pro_git.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/ysyun/pro_git.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. If you did not intend to push that branch, you may want to
hint: specify branches to push or set the 'push.default' configuration
hint: variable to 'current' or 'upstream' to push only the current branch.
////////////////////////////////////////////////////////////////////////////
// origin/master를 local 저장소로 가지고 온다.
$ git fetch
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/ysyun/pro_git
d895a7e..9274820 master -> origin/master
////////////////////////////////////////////////////////////////////////////
// rebase를 위하여 master로 이동한다
$ git branch
* (no branch)
master
$ git checkout master
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
bbeb691 add content in rebase of local repo
If you want to keep them by creating a new branch, this may be a good time
to do so with:
git branch new_branch_name bbeb691d80512e17279764312f60416ebf28dd86
Switched to branch 'master'
Your branch and 'origin/master' have diverged,
and have 1 and 3 different commits each, respectively.
$ git branch
* master
////////////////////////////////////////////////////////////////////////////
// rebase를 수행한다.
// rebase.html 파일 내역에서 conflict가 나온다고 메시지를 출력한다
$ git rebase
First, rewinding head to replay your work on top of it...
Applying: updating rebase in local repo.
Using index info to reconstruct a base tree...
M rebase.html
Falling back to patching base and 3-way merge...
Auto-merging rebase.html
CONFLICT (content): Merge conflict in rebase.html
Failed to merge in the changes.
Patch failed at 0001 updating rebase in local repo.
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".
$ git status
# Not currently on any branch.
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: rebase.html
#
no changes added to commit (use "git add" and/or "git commit -a")
////////////////////////////////////////////////////////////////////////////
// rebase.html 파일 내역을 보고 적절히 수정한다
$ cat rebase.html
this is rebase html file ok
<<<<<<< HEAD
updating rebase in remote repo. again
add content in remote repo.
=======
updating rebase in local repo.
>>>>>>> updating rebase in local repo.
$ vi rebase.html
$ cat rebase.html
this is rebase html file ok
updating rebase in remote repo. again
add content in remote repo.
updating rebase in local repo.
////////////////////////////////////////////////////////////////////////////
// rebase.html 을 staging area로 add 한다.
$ git add rebase.html
////////////////////////////////////////////////////////////////////////////
// rebase를 계속 진행한다
$ git rebase --continue
Applying: updating rebase in local repo.
////////////////////////////////////////////////////////////////////////////
// commit log를 확인해 보면 rebase가 되어서 remote commit 내역이 local 저장소에
// 복사되었다.
$ git log --pretty=oneline
30d42e6785e441c3b515a4f4181dbfa051ad400a updating rebase in local repo.
9274820a9f62b2e08411ffb34d808508c7a74f93 add content in rebase of remote repo
d895a7e83d85d05f2c81585232f9c3e22426383a updating rebase again in remote repo
8c7c04b40d9fce0a1ae5a52b45b438fa14ea95e1 Update rebase.html
////////////////////////////////////////////////////////////////////////////
// 다시 push를 하면 정상적으로 remote 저장소로 push 가 된다
$ git push
Username for 'https://github.com':
Password for 'https://ysyun@yuwin.co.kr@github.com':
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 323 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://github.com/ysyun/pro_git.git
9274820..30d42e6 master -> master
// remote에 local에서 직접 수정한 내역이 commit 됨
// local repo(파란색, 30d42e6785)의 SHA 값이 가장 상위에 그 다음 remote repo 의 SHA(927480a9f...)가 밑에 있다.