git workflow 중 centralized 방식에 대해 step-by-step 으로 실제 사례를 보도록 하겠습니다.
간단한 시나리오는 다음과 같습니다.
여러분과 함께할 두 명의 개발자, 철수와 영희가 고용되었습니다. 철수와 영희는 각각에 대한 기능을 개발할 것이고, 철수가 먼저 완성시키고 영희는 철수보다 늦은 죄로 conflict 를 경험하게 됩니다. 이를 해결하며 어떻게 중앙저장소의 commit history를 유지하는지 같이 보도록 합시다.
1. 프로젝트 시작하기
ssh user@host
git init --bare /path/to/repo.git
git clone ssh://user@host/path/to/repo.git
git status # View the state of the repo
git add # Stage a file
git commit # Commit a file
git push origin master
이제 마침 영희도 개발을 끝냈습니다. 영희는 다음처럼 철수와 똑같이 push 하려고 시도할 것입니다.
git push origin master
결국 push는 실행되지 않습니다. 어떻게 해야할까요?
다음으로 영희가 할 일은 철수의 update 를 자기의 local 저장소로 당겨와야합니다.(pull) 그리고 local 변화를 통합한 후 새로 시도하는 것이 해결책입니다. 다음을 보면서 얘기도록 하겠습니다.
7. 영희의 rebase
영희는 git pull 을 사용하여 자신의 local 저장소에 중앙저장소의 최신 흐름 (여기서는 철수가 push한 commit들) 을 불러올 수 있습니다. 이 명령어는 svn update 와 유사하게 동작합니다.
git pull --rebase origin master
--rebase 옵션은 아래 그림과 같이, 중앙저장소로부터의 변경사항을 동기화 시키고 난 후 영희(Mary)의 모든 commit을 master branch로 옮길 것을 미리 지정하는 역할을 합니다.
이 옵션을 쓰지 않아도 pull 은 잘 동작합니다. 그러나 나중에 매번 불필요한 "merge commit"을 해야할 수도 있으므로 --rebase 옵션을 추천합니다. 이번 Centralized workflow에서는 merge commit 보다는 rebase가 항상 더 좋은 결과를 냅니다. (commit history 를 선형으로 유지하기 쉽기 때문입니다)
8. 영희의 conflict 해결법
Rebase는 각각의 local commit을 master branch로 하나씩 전송하면서 동작합니다. 이는 곧 하나의 큰 merge commit에 대한 conflict를 해결하는 것 보다는 조그만 commit을 베이스로 conflict를 잡아내고 수정하는 것이 더 나음을 의미합니다. 또한 Rebase는 여러분의 commit에 좀 더 포커스를 맞추고, 프로젝트 history를 깨끗하게 만들어줍니다. 버그가 발생했을 때, 가능한 작은 임팩트를 주는 곳으로 roll back 하는 것이 훨씬 버그를 잡는데 유용합니다.
설명이 길어졌는데, 결론은 commit을 자주 하라는 것입니다.
다시 본론으로 돌아와서, 철수와 영희가 서로 관련없는 기능들을 개발했다면 위와 같은 rebase 과정들이 conflict를 만들어내진 않을 것입니다. 그러나 겹치는 부분이 있다면, git는 현재 commit에서 rebase 를 멈추고 다음과 같은 메시지를 내보일 것입니다.
CONFLICT (content): Merge conflict in <some-file>
git의 장점 중 하나는, 누구나 merge conflict를 해결할 수 있다는데에 있습니다. 흔히 git status 명령어를 사용하면 어디가 문제인지 알 수 있는데, conflict가 생긴 파일은 다음처럼 unmerged path section 에 나타날 것입니다.
# Unmerged paths:
# (use "git reset HEAD <some-file>..." to unstage)
# (use "git add/rm <some-file>..." as appropriate to mark resolution)
#
# both modified: <some-file>>
그러고난 후 영희는 그녀가 원하는대로 해당 파일을 수정할 것입니다. 수정이 끝난 후 아래처럼 다시 git add를 통해 파일을 stage 상태로 만들고, git rebase로 나머지 작업을 마무리 짓습니다.
git add <some-file>
git rebase --continue </some-file>
여러분이 여기까지 오셨는데도 이해를 거의 못했다고해서 당황할 필요는 없습니다. 단지 아래 명령어를 실행하는 것만으로도 여러분은 시작점으로 쉽게 돌아갈 수 있습니다. git pull --rebase
git rebase --abort
9. 마무리
위와 같이 영희의 동기화 작업이 끝나면, 그 변경작업들이 성공적으로 push 되어질 수 있을 것입니다.
git push origin master