(4)-5.GERRIT - F.+Conflict+resolve+&+pull
F. Conflict resolve & pull
Conflict, Merge in Gerrit
- 이번엔, 하나의 프로젝트를 두 명의 개발자가 같이 개발하고 있는 상황에서, conflict가 났을 때 리뷰어가 직접 conflict을 수정하여 merge하는 상황을 실습해보겠습니다.
- 3명의 역할을 가정하기 때문에 다소 정신이 없습니다. 알고 보면 간단한데, 어려워 보일 수 있으니 유심히 봐주세요.
- 새로 프로젝트를 만들어 클론하고, 이를 3개로 복사해서 각각 dev1, dev2, reviewer 3개의 workspace를 만들겠습니다.
$ git clone ssh://admin@localhost:29418/conflict_rework && scp -p -P 29418 admin@localhost:hooks/commit-msg conflict_rework/.git/hooks/
Cloning into 'conflict_rework'...
remote: Counting objects: 2, done
remote: Finding sources: 100% (2/2)
remote: Total 2 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2/2), done.
commit-msg 100% 4691 570.0KB/s 00:00
$ cp -R conflict_rework/ dev1
$ cp -R conflict_rework/ dev2
$ cp -R conflict_rework/ reviewer
- dev1 과 dev2는 각각의 workspace에서 작업을 한 후 각각 "C001" , "C002" 라는 이름으로 review commit 을 요청했습니다.
$ cd dev1
$ echo "This is created by dev1" > conflict.txt
$ cat conflict.txt
$ git add *
$ git commit -m "C001"
$ git push origin HEAD:refs/for/master
$ cd ../dev2
$ echo "This is created by dev2" > conflict.txt
$ git add *
$ git commit -m "C002"
$ git push origin HEAD:refs/for/master
- C001, C002 커밋이 All → Open을 보면 잘 올라와 있습니다.
- 일단 C002 커밋을 눌러서 자세히 보겠습니다. C001과 Conflict이 나고 있다고 gerrit이 알려주는 군요.
- gerrit이 뭐라고 하던, 일단 C002 커밋을 review 를 통과시켜보겠습니다. merged에 C002 커밋이 잘 들어가 있는 것을 볼 수 있습니다.
- 이제 다시 C001 commit으로 돌아와 보니, Cannot Merge라고 떠있군요. 이 상황을 해결하지 못하면 해당 커밋을 merge할 수가 없습니다.
- 여러 경우가 있겠지만, 여기서는 review가 merge된 C002와 review중인 C001을 둘 다 받아와서, conflict를 해결하고, 다시 review push 하여, conflict를 해결해보겠습니다.
$ cd ../reviewer/
$ git pull : 현재 merge된 C002를 pull로 가져옵니다.
$ cat conflict.txt
This is created by dev2
$ git fetch ssh://admin@localhost:29418/conflict_rework refs/changes/03/103/1 && git checkout FETCH_HEAD
: 그리고 C001로 가서 download의 fetch URL을 가져옵니다.
$ cat conflict.txt : 가져온 내용을 보니, C001에서 작성한 내용이군요.
This is created by dev1
$ git checkout -b conflict : FETCH_HEAD를 master에 합치기 위해, 임시로 conflict란 branch를 생성해서, fetch된 내역을 옮겨줍니다.
$ git rebase master : conflict 상황을 merge하면, amend가 안되므로 master에 rebase하는 전략으로 진행하겠습니다.
First, rewinding head to replay your work on top of it...
Applying: C001
error: Failed to merge in the changes.
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging conflict.txt
CONFLICT (add/add): Merge conflict in conflict.txt
Patch failed at 0001 C001
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
$ cat conflict.txt : 예상대로 conflict이 났습니다. 그에 따라 rebase가 중단되었습니다. 자세히 읽어보니, 해결하고, continue 하란 말이 있습니다.
<<<<<<< HEAD
This is created by dev2
=======
This is created by dev1
>>>>>>> C001
$ vi conflict.txt : 둘 다 살리는 것으로 conflict 를 해결하겠습니다.
$ git add *
$ git rebase --continue : 방금 메시지에서 나온대로, continue option으로 rebase를 진행합니다.
Applying: C001 : fetch해온 C001이 master로 잘 옮겨졌습니다.
$ git checkout master
$ git merge conflict : 마무리를 위해 master로 이동하여, 임시로 conflict branch에 보관한 내용을 병합해줍니다.
$ git add *
$ git commit --amend : 다시 스테이징하고, amend로 현재 commit을 수정하여 리뷰 요청합니다.
$ git push origin HEAD:refs/for/master
- 리뷰어가 요청한 커밋이 잘 제출되었음을 볼 수 있습니다.
- Conflict가 잘 해결되어, 바로 submit할 수 있음을 알 수 있습니다.
- submit 이 완료된 후, dev1, dev2 각각의 workspace에 가보면, 최신 내용이 반영되어 있지 않은 것을 알 수 있습니다. 이 때 git pull을 수행하여, gerrit에 최종반영된 버전과 현재 작업 내역을 merge합니다.
$ cd dev2
$ cat conflict.txt : dev에서 작업한 내역만 들어 있습니다.
This is created by dev2
$ git pull : git pull로 gerrit에서 최종 반영된 버전과 현재 작업되고 있는 내역을 merge합니다.
remote: Counting objects: 5, done
remote: Finding sources: 100% (3/3)
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From ssh://localhost:29418/conflict_rework
f1a087f..f23b940 master -> origin/master
Updating 6dd3307..f23b940
Fast-forward
conflict.txt | 1 +
1 file changed, 1 insertion
$ cat conflict.txt : 현재 작업 내역에 dev1이 작업한 내역이 잘 merge
This is created by dev2
This is created by dev1
- 만약 git pull 하는 과정에서 Conflict이 다시 발생하면, git log로 커밋 History 확인 후 git reset --hard HEAD~1 으로 최신 커밋을 삭제한 후, 다시 git pull을 수행합니다.