1. 브랜치 이해하고 활용하기
1.1. 브랜치란
Git의 비밀을 말해보자면 지금까지 한 모든 작업도 사실 master라는 브랜치에서 진행했다.
Git은 모든 것을 브랜치로 다룬다.
따라서 마스터 브랜치명을 바꾸지 못할 이유도 없다.
$ git branch –m master mymaster $ git branch |
master 브랜치를 mymaster로 변경했다.
첫째 명령은 3개의 매개변수를 지정했다.
–m 매개변수는 이동을 의미하며, 다른 2매개변수는 변경하려는 브랜치명과 새로 바꾸려는 브랜치명이다.
둘째 명령은 git branch만 사용했다.
매개변수를 지정하지 않으면 Git은 지역저장소에 있는 브랜치명을 모두 표시한다.
현재 저장소에는 하나의 브랜치만 있으므로 브랜치명을 한 개만 표시한다.
Git에서는 모든 게 브랜치로 간주되므로, 브랜치를 생성하는 비용이 크지 않다.
모든 파일을 새로운 디렉터리로 복사하는 다른 시스템과는 다르게,
Git의 브랜치는 해당 브랜치가 만들어진 시점부터 적용된 커밋만 추적한다.
엄밀히 말하면 이것도 진실은 아니다.
Git의 브랜치는 최신 커밋만을 추적한다.
최신 커밋에는 부모 링크가 있고, 이 링크를 사용하여 Git은 브랜치에 있는 모든 변경 사항을 찾을 수 있다.
사실 브랜치를 생성할 시기를 결정하는 것이 가장 어렵다.
l 실험적인 변경사항
성능이 향상되는지 알아보려고 알고리즘을 다시 작성하거나, 코드의 일부를 특정 패턴으로 리팩터링하려고 하는가? 그렇다면 브랜치를 생성하라.
그러면 배포를 앞두고 있는 변경 사항과는 상관없이 원하는 작업을 해 볼 수 있다.
l 새로운 기능
새로운 기능을 추가할 때마다 브랜치를 생성하라.
작업이 끝나면 브랜치를 합칠 수 있다.
이때 브랜치의 전체 변경 이력을 가져오거나, 모든 이력을 하나의 커밋으로 합쳐서 가져올 수도 있다.
2가지 합치는 방식에 대해서는 5.3절.
l 버그 수정
아직 릴리스 하지 않은 코드의 버그거나, 릴리스 하려고 태그를 붙인 코드의 버그에 상관 없이, 버그와 관련된 변경 사항을 추적할 수 있도록 브랜치를 생성하라.
새로운 기능을 추가하는 브랜치와 마찬가지로, 수정한 부분을 기존의 코드에 반영할 때 매우 유연해진다. 특히 수정한 버그에 확신이 서지 않을 경우에 적합하다.
1.2. 새로운 브랜치 생성하기
다음은 new라는 브랜치를 생성한다.
$ git branch new |
Git은 새로운 브랜치가 생성됐음을 알려주지는 않지만, 매개변수를 지정하지 않고 git branch를 실행하면 확인할 수 있다.
$ git branch * master new |
새로운 new 브랜치가 생성됐음을 알 수 있다.
master 브랜치명 옆에 별표가 있음에 유의하자.
별표는 해당 브랜치가 현재 체크아웃된 상태임을 의미한다.
체크아웃된 브랜치는 현재 작업 트리를 나타내는 브랜치다.
새 브랜치는 파일 변경을 하기 위해 만들었다.
파일 변경을 하기 전에 브랜치를 먼저 체크아웃해야 한다.
다음과 같이 checkout 명령어를 사용하여 브랜치를 체크아웃한다.
$ git checkout new |
대부분은 브랜치를 생성할 때 새로운 브랜치로 바로 체크아웃하려고 할 것이며, 그런 경우 즉시 작업을 시작할 수 있다.
브랜치를 생성할 때는 작업을 시작하는 경우가 많으므로, 새로운 브랜치로 바로 체크아웃하는 것이 편하다. 이 방법도 Git에서는 제공한다.
git checkout 명령어에 –b 매개변수를 추가하면, 브랜치의 생성과 체크아웃을 한 번에 할 수 있다.
git checkout –b 를 실행하여 다른 브랜치를 생성해 보자.
각 브랜치는 고유한 이름이어야 한다.
따라서 master나 new를 제외한 다른 이름을 지정해야 한다.
$ git checkout –b alternate master |
3 번째 매개변수 master는, Git이 현재 브랜치 대신 master 브랜치로부터, 새로운 브랜치를 생성하도록 한다.
물론 git branch로 새로운 브랜치를 생성하는 경우도, 추가적인 매개변수를 지정할 수 있으며, 그러면 Git은 지정한 브랜치로부터 새로운 브랜치를 생성한다.
1.3. 브랜치 간의 변경 사항 합치기
합치기는 말 그대로 2개 혹은 그 이상의 브랜치를 하나로 합치는 것이다.
브랜치 간의 변경 사항을 합치는 방법에는 몇가지가 있는데,
이 절에서는 다음 3가지를 살펴본다.
l 바로 합치기(Straight Merge)는 하나의 브랜치와 다른 브랜치의 변경 이력 전체를 합치는 방법이다.
l 커밋 합치기(Squashed Commit)는 한 브랜치의 이력을 압축하여 다른 브랜치의 최신 커밋 하나로 만드는 방법이다.
l 선택하여 합치기(Cherry-picking)는 다른 브랜치에서 하나의 커밋을 가져와서 현재 브랜치에 적용하는 방법이다.
1.3.1. 바로 합치기(Straight Merge)
하나의 브랜치를 선택해서 다른 브랜치와 합친다.
해당 브랜치의 전체 이력을 다른 브랜치에 반영하고자 할 때 사용한다.
앞에서 생성한 alternate 브랜치에 새로운 변경 사항을 추가하여 합치기를 시도해 보자.
about.html 파일을 추가하고, 약간의 정보를 추가한다.
새 파일을 생성했다면, 저장소에 추가하고 커밋한다.
$ git add about.html $ git commit –m “add the skeleton of an about page” |
현재 alternate 브랜치에 커밋한 내용은 master 브랜치에 존재하지 않는다.
이제 git merge를 이용하여 2 브랜치를 합칠 수 있다.
먼저, 현재 브랜치를 합치고자 하는 대상 브랜치로 전환해야 한다.
여기서는 master 브랜치다.
$ git checkout master |
그 다음 git merge를 실행한다.
가장 간단한 형태로는 git merge에 현재 브랜치에 합치려는 브랜치명을 지정하면 된다.
$ git merge alternate |
이제 alternate 브랜치의 변경 사항이 master 브랜치에 합쳐졌다.
1.3.2. 커밋 합치기(Squashed Commit)
Git이 브랜치 하나의 모든 이력을 압축하여, 다른 브랜치에 하나의 커밋으로 만들기에 커밋 합치기라고 한다.
커밋합치기를 할 때는 유의해야 한다.
이력에서 모든 커밋은 대부분 독자적으로 유지되어야 한다.
브랜치에서 변경한 내용들이 하나의 변경 사항으로 볼 수 있다면, 커밋 합치기를 사용할 후보이다.
커밋 합치기는 이것저것 실험해 봐야 하는 새로운 기능을 만들거나 버그를 수정할 때 유용하다. 실험한 내용은 추적하지 않아도 되므로 커밋할 필요가 없다. 즉 마지막 결과만 필요할 뿐이다.
커밋 합치기를 하려면 합치려는 대상이 필요하다.
master 브랜치에서 contact 브랜치를 생성하고 체크아웃 한다.
$ git checkout –b contact master |
contact.html 파일을 추가한 다음 메일 주소를 입력하고 커밋.
$ git add contact.html $ git commit –m “add contact file with email” |
추가 메일 주소를 입력하면 연락할 방법이 2가지가 된다. 그리고 다시 커밋
$ git commit –m “add secondary email”–a |
이제 contact 브랜치에는 2개의 커밋이 존재한다.
2개의 커밋을 master 브랜치에 한 개의 커밋으로 밀어 넣을 수 있다.
먼저 master 브랜치로 다시 전환.
$ git checkout master |
git merge 할 때 –squash 를 지정한다.
squash를 추가하면 git merge에서 지정한 브랜치의 모든 커밋을 하나의 커밋으로 밀어 넣는다.
$ git merge --squash contact |
contact 브랜치에 있는 2개의 커밋이 작업 트리에 적용되어 스테이징 됐지만, 아직 커밋까지 되지는 않았다.
변경사항을 확인하려면 git status를 실행
커밋한다.
$ git commit –m “add contact page”\ |
1.3.3. 선택하여 합치기(Cherry-picking)
때로는 브랜치 간에 전체를 합치는 대신, 오직 하나의 커밋만 합칠 필요가 있다.
브랜치에 아직 사용할 수 없는 기능이 있거나,
해당 브랜치에는 아직 준비가 안 된 변경 사항이 있을 수 있기 때문에, 전체 합치기가 적합하지 않은 경우가 있다.
그렇다면 언제 하나의 커밋을 밀어 넣어야 하나? 수정된 버그나 브랜치들 사이에 공유해야 하는 클래스를 추가하는 경우가 이러한 상황에 해당한다.
git cherry-pick 을 사용하면 개별적인 커밋을 밀어 넣을 수 있다.
현재 브랜치가 contact인지 확인한다.
$ git checkout contact |
브랜치를 전환했으니 그 다음은 트위터 계정 같은 연락할 수 있는 새로운 링크를 추가하고 커밋한다.
$ git commit –m “add link to twitter”–a |
추가된 커밋명은 ‘321d76f’이다.
이 커밋명을 이용하면 어디서나 선택하여 합칠 수 있다.
이제 해당 커밋을 master로 가져가자.
$ git checkout master $ git cherry-pick 321d76f |
선택하려는 커밋이 여러 개라면 git cherry-pick에 –n 매개변수를 지정한다.
-n 매개변수는 Git을 합치기는 하지만 커밋하지 않게 만든다.
먼저 git reset으로 바로 전 커밋을 제거한다.
이 명령어는 6.6절. ‘변경 취소하기’.
$ git reset –hard HEAD^ |
이제 마지막 커밋이 제거되었고, -n 매개변수를 지정하여 git cherry-pick을 다시 실행할 수 있다.
$ git cherry-pick –n 321d76f |
Git이 ‘선택하여 합치기 완료(Finished on cherry-pick)’에서 중단되었다.
git status를 하여 새로운 파일이 추가되었고, 스테이징되어 커밋할 준비가 됐음을 확인할 수 있다.
이제 계속해서 다른 변경 사항을 선택하여 합칠 수 있다.
선택한 커밋을 모두 가져온 후 원하는 대로 메시지를 지정하여 커밋할 수 있다.
가져오기가 끝났다면 변경 사항을 커밋하자.
커밋할 때 메시지를 추가하는 –m 매개변수를 지정하지 않아도 된다.
편집기가 실행되면 기본적으로 가져온 커밋의 메시지가 나타남을 볼 수 있다.
$ git commit |
1.4. 충돌 다루기
Git에서 커밋을 자동적으로 합칠 수 없는 경우를 충돌이라고 한다.
충돌은 각 브랜치에서 파일의 동일한 영역을 다르게 변경할 경우 흔히 나타난다.
Git은 사용자가 어떤 것을 원하는지 알 수 없으므로 충돌로 판단해서 실행을 멈추고 사용자가 수정하도록 한다.
합칠 내용이 간단하다면 충돌이 발생한 부분을 직접 수정한다.
변경사항을 저장하고, 일반적인 경우와 마찬가지로 변경사항을 스테이징하고 커밋한다.
복잡한 내용을 합칠 때는 코드를 비교하면서 합칠 수 있는 도구가 유용하다.
리눅스에는 kdiff3이 있으며, OS X에는 opendiff가 있다.
git mergetool 명령어로 합치기 도구를 실행할 수 있다.
git mergetool 을 실행하면 합치기 도구를 찾으려고 시도하는데,
때로는 도구가 여러 개 존재할 수 있다. 이럴 때는 사용할 도구를 선택해야 한다.
git mergetool은 구성에 있는 merge.tool 값을 확인하여, 합치기에 적합한 도구가 있는지 시스템에 확인한다.
적합한 도구에는 kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, opendiff가 있다.
충돌을 성공적으로 해결했다면, Git은 변경 사항을 커밋할 수 있도록 스테이징한다.
바로 변경 사항을 커밋하자. –m 옵션을 생략하면, 방금 일어난 사항을 설명하는 메시지가 채워진 편집기가 실행된다.
1.5. 브랜치 삭제하기
git branch –d 로 오래된 브랜치를 삭제할 수 있다.
$ git branch –d about2 |
브랜치 삭제 명령은 삭제하려는 브랜치가 성공적으로 현재 브랜치에 합쳐졌을 때만 동작한다.
$ git checkout master $ git branch –d about |
about 브랜치를 합치지 않고 삭제하기를 원한다면, -d 대신 –D를 지정하여 강제로 삭제할 수 있다.
-D는 Git이 삭제하려는 브랜치가 현재 브랜치에 합쳐졌는지 확인하지 않고 삭제한다.
1.6. 브랜치명 변경하기
브랜치명을 contacts로 변경한다.
$ git branch –m contact contacts |
-m 은 존재하는 브랜치를 덮어쓰지 못하므로, 새로운 브랜치명은 반드시 고유해야 한다.
만약 존재하는 브랜치 명으로 바꾸려고 한다면 에러 메시지를 출력한다.
-m 대신 –M 옵션을 지정하면 덮어쓰도록 동작을 바꿀 수 있다.
Git이 해당 이름을 가진 브랜치가 존재하더라도 강제로 덮어쓰게 하므로 주의하자.
'형상관리 > Git' 카테고리의 다른 글
Git, 분산버전 관리시스템(11) - Git으로 옮겨가기 (0) | 2012.04.23 |
---|---|
Git, 분산버전 관리시스템(10) – 기본을 넘어서 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(9) - 저장소 조직하기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(8) - 원격 저장소를 이용하여 작업하기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(7) - Git 이력 이용하기(2) – 변경 취소하기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(6) - Git 이력 이용하기(1) – 로그/리비전범위/버전간차이점/blame/내용따라가기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(4) – Git 기초: 추가하고 커밋하기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(3) – 첫 프로젝트 만들기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(2) - Git 설정하기 (0) | 2012.04.23 |
Git, 분산버전 관리시스템(1) - Git 방식으로 버전 관리하기 (0) | 2012.04.23 |