ALM/SCM/VCS

git 사용법과 소스 관리

Terry Cho 2013. 7. 28. 01:00

 소스 코드 관리와 git

조대협 (bwcho75@지메일)

소프트웨어 개발에 있어서소스코드의 관리는 중요한 포인트 중의 하나이다다양한 버전과 변경 관리협업을 위해서는 소스코드를 저장 및 관리할 수 있는 시스템이 필요하고이를 VCS (Version Control System) 또는 SCM (Source Code Management) System이라고 한다소스코드 관리 시스템의 주요 기능은 다음과 같다.

협업을 위한 코드 공유 - 여러 사람들이 협업을 할 경우코드를 각 개발자와팀간에 공유할 수 있어야 하며

접근 제한사용자의 권한 등급에 따라 접근을 제한해야 한다.

다양한 버전(형상) 관리소프트웨어 개발 버전 또는 릴리즈 (브랜치마다다른 코드를 저장할 수 있어야 한다예를 들어 릴리즈된 버전이나 마이너 버전에 대한 코드 관리패치 코드 관리 등이 그 예가 될 수 있다. 또한 다양한 브렌치중 두개 이상의 브렌치를 하나의 코드로 합칠(merge)할 수 있어야 한다.

특정 시점 추적 태깅 설명

변경 추적 - 마지막으로각 코드에 대한 변경을 추적할 수 있어야 한다누가언제어떤 이유로 코드를 어떻게 변경을 했는지를 추적하여 문제 발생시 원인 분석을 할 수 있어야 한다.

1)   Branch

먼저 소스코드 관리에 대한 개념 이해를 위해서는 Branch의 개념 이해가 필요하다소프트웨어 개발을 할 때하나의 저장소에 소스코드를 저장해서 개발하고개발자간의 공유를 해서 협업을 진행한다.

 개발을 진행하다가 특정 목적에 의해서 별도의 작업에 의해예를 들어 영문으로 된 버전을 중국어나 한국어로 제공하기 위해서는 기존 개발 소스코드의 복사본을 만들어서,중국어 개발용으로 하나 사용하고한국어 개발용으로 하나 사용 한다이렇게 새롭게 만들어진 소스코드의 복사본 (중국어버전한국어 버전)을 브랜치라고 하고원래 소프트웨어를 개발하던 소스코드 저장소를 메인 브랜치(또는 trunk version, head version)이라고 한다.

이렇게 코드의 원본에서 용도와 목적에 따라서 새로운 복사본을 만들어 나가기 때문에,메인 코드에서 복사본을 나뭇가지 (Branch)라고 하고이 모양이 마치 나무와 같은 구조가 되기 때문에, Source Code Tree또는 Branch Tree라고 한다.

2)    Check Out / Commit & merge

소스코드 저장소를 만들었으면 해야 할 일이 코드를 저장하거나 내려 받는 일이다.

코드를 내려 받는 행위를 Check Out이라고 하고작성된 코드를 저장소에 업로드 하는 행위를 Commit이라고 한다.

VCS의 종류에 따라서 Check Out된 코드의 경우다른 사람이 편집을 할 수 없고read만 할 수 있도록 lock을 걸 수 도 있다. (VCS 종류에 따라 다르다). 이 경우 다른 사람이 내가 편집하고 있는 코드를 편집할 수 없기 때문에코드 작성에는 문제가 없지만 반대로 다른 개발자는 lock이 풀리기 까지 기다려야 하기 때문에협업에 문제가 발생할 수 있다그래서 lock을 걸지 않고 코드를 동시에 2인 이상이 코드를 다운받아 편집할 수 있는 방법을 제공하는데이 경우 코드를 Commit을 할 경우한 파일을 다운 받아서 각자 편집을 하고 저장을 시도할 경우코드상 Conflict(충돌)이 발생한다.

 즉 개발자 A,B가 소스 코드 버전 1 Check Out 받았다고 하자개발자 A가 소스코드 2번 라인에 "printf('hello world')" 라는 코드를 추가하고 Commit을 해서 코드 버전이 2가 되었다고 했을 때, B도 역시 2번 라인에 "printf('hello developer')" 라는 코드를 추가하고 Commit을 하려고 하면, A B가 편집한 내용이 충돌이 생긴다둘다 1번 버전의 코드를 가지고 수정을 하였으나공교롭게 개발자 A,B 가 같은 파일을 수정하였기 때문에 VCS 입장에서는 B 개발자가 수정한 내용을 반영하게 되면A개발자가 반영한 내용이 없어져 버리기 때문에 문제가 될 수 있다.

이런 경우 VCS에서 B Commit하려는 코드가 현재 버전인 2 버전에 의해서 편집 된것이 아니라는 것 을 알려주고개발자 B에게 선택을 하도록 하는데, 2 버전 코드와 다른 내용을 병합 (merge)하게 하거나, 3버전의 코드를 Overwrite하여 2버전의 코드 변경 내용을 무시할 수 있도록 한다.

대부분의 경우에는 당연히 다른 개발자의 변경 내용을 무시할 수 없기 때문에, merge를 선택하게 되고, merge는 개발자B 2번 버전과의 로직의 차이를 일일이 확인하면서 수동으로 merge를 하도록 한다.

3)   Update

Update의 개념은 개발자가 소스 코드를 Check Out 받아 놨을 때현재 작업 버전이 오래되거나또는 다른 개발자가 Commit을 먼저 해서, VCS의 소스코드 버전이 올라갔을 때, VCS Local의 코드를 동기화 시키기 위해서 사용한다.

위에서 설명한 Commit시 발생하는 Conflict(충돌시나리오와 마찬가지로내가 변경한 코드와 다른 개발자에 의해서 변경된 코드가 Conflict이 발생할 수 있으며앞에서 설명한 방법과 같은 방법으로 수동으로 코드의 변경 부분차이 나는 부분)을 병합하도록 한다.

4)   Tagging

다음으로 Tagging이라는 개념을 알아보자, Tagging 이란코드를 개발 중에특정 시점의 이미지에 표시를 해놓는 것을 의미한다예를 들어매일 소스코드에 대한Tagging을 달아놓으면개발 중에 문제가 생겼을 경우에특정 날짜의 소스 코드로 다시 돌아갈 수 가 있다.

Tagging은 주로, Build 시마다 하는 경우가 많은데 (이를 빌드 태그라고 함). 통상 적으로 빌드시 에러가 날 경우에 다른 개발자들이 빌드 에러로 인하여 개발을 못하는 경우가 생길 수 있기 때문에이런 경우에는 이전 Build시 태그해놓은 버전으로 소스코드를 돌려서 다시 개발을 수행하고문제가 해결 되면새로운 코드를 다시Commit 하는 방식으로 개발을 진행한다.

5)    Release Branch

다음으로 Branch Release Branch에 대한 설명이다.

패키지 소프트웨어 개발 프로세스를 생각해보자예를 들어서버 제품을 개발하여,출시를 했다고 하자현재 개발 중인 메인 Branch 에서 해당 시점에 릴리즈를 했다.릴리즈한 서버의 버전은 6.1이다메인 branch 로는 계속해서 신제품 개발을 이어나가고 7.0 개발을 진행 중이었다.

이때, 6.1을 사용하던 고객에게서 버그 수정 요청이 온경우 어떻게 해야 할까?

6.1 코드에 일부 코드만 수정하여 패치를 발급하면 되지만메인 branch의 경우 이미 7.0 버전 개발을 위해서 코드 개발이 많이 진행되었기 때문에 6.1 에 대한 코드는 바뀌어서 찾을 수 가 없고 7.0 버전 역시 개발이 완료되지 않아서 수정이 불가능하다.

이런 시나리오를 방지하기 위해서 패키지 형태의 소프트웨어 개발은 각 릴리즈 마다release branch를 발급하는 것이 좋다.

우리가 사용하는 Windows , Windows XP,7등으로 release를 하지만 Service Pack이나 필수 패치등을 발급하는 것은 각 release  branch를 발급한 뒤에, branch 별로 패치나 service pack것과 같은 원리이다.

이런 release branch는 웹서비스 (face book )의 경우하나의 코드가 하나의 서비스에만 배포가 되기 때문에별도의 release branch를 유지하는 것 보다는release tagging을 한 후에이슈가 있을 경우 이슈를 fix한 최신 버전을 다음release 때 배포 하는 방식등을 주로 사용하기 때문에, release branch의 효용성이 패키지 소프트웨어에 비해서 떨어진다.

6)   QA branch

다음으로 사용할 수 있는 branch중 하나는 QA branch 이다. production 으로 (상품화 하기 위해개발팀에서 source code freezing 하고 QA 팀에 해당 제품을 넘겨서 테스트를 의뢰할 경우, QA팀에서 계속해서 버그 수정 요청을 해오게 된다이 때버그를 main branch에서 계속해서 수정을 하게 되면, main 개발에 많은 수정이 가해지기 때문에 개발이 어려워질 수 있다. (merge도 많이 발생하고번거로움그리고, main branch에서는 개발이 계속 진행되기 때문에, feature 변경이나 기타 수정이 있을 경우 QA에 의해서 reporting된 버그가 제대로 재현이 되지 않는 경우가 있을 수 있다그래서 QA에 넘기기 전에 QA branch를 따고버그에 대한 fix를 이QA branch에서 수행 및 반영 한다.

QA가 모두 완료되고 나면 QA branch에 있는 변경 내용을 다시 main branchmerge하여, bug 수정 내용을 반영하도록 한다.

7)    소스 코드 브랜치 관리 전략

앞서 살펴본 바와 같이 사실 branch main code (branch)의 복사본이다용도에 따라서 얼마든지 만들 수 있고필요에 따라 merge를 할 수 도 있다그러나 패키지냐웹서비스냐와 같은 소프트트웨어의 종류와팀의 크기와 구조 , 릴리즈 정책등에 따라서 어떠한 branch를 언제 사용할지가 다르기 때문에개발하는 소프트웨어의 형상에 따라서 알맞은 branch 전략을 결정해야 한다.

또한 VCS 제품에 따라, 몇몇 제품의 경우에는 이미 자사 제품 특성에 맞는 브렌치 구조에 대한 레퍼런스를 제공하거나, 또는 성격에 따라 맞는 레퍼런스 브렌치 모델이 많이 공개되어 있다.

또 다른 방법으로는 오픈소스에서 사용하고 있는 소스 코드의 tree 구조를 레퍼런스 해보는 것도 좋은 방법이다.

다음은 몇 가지 유용한 브렌치 구조에 대해서 소개하도록 한다.

오픈소스 소스 코드 브렌치 관리 전략

다음은 요즘 많이 사용하는 VCS 솔루션의 하나인 git를 이용한 branch 전략이다.


[1]

이 브렌치 구조는 이미 git flow라는 이름으로, git를 사용하는 사람들에게는 널리 알려져 있는 브렌치 모델이다. 이 구조는 오픈소스와 같이 대규모의 분산된 개발 조직이 서비스나 오픈소스 제품을 만드는 구조에 매우 적합니다.

http://nvie.com/posts/a-successful-git-branching-model/

그리고, 이 구조대로, git의 저장소를 정의하고, 쉽게 사용할 수 있도록 git flow라는 오픈소스 도구를 제공한다. https://github.com/nvie/gitflow

개념을 살펴 보면, main branch에서는 개발을 진행하지 않고별도의 develop branch를 만들어서 여기서 개발을 진행한다기능 (feature) 별로 feature branch를 별도로 만들어서 개발을 진행하고 feature 개발이 완료되면, develop branch merge를 한다.

master develop branch의 관계는 재미있는 개념이 있는데, 바로 code review이다. 개발자가 코드 수정을 하였을 경우, Jenkins 등의 빌드 시스템에 통합되서 빌드되고, 테스트되어야 동작 여부를 확인할 수 있기 때문에, 어딘가 코드를 공유할 수 있는 장소가 필요하다. 즉 개발이 완료된 부분은 먼저 develop branch에 저장되서 컴파일 및 테스트를 끝내고, code review를 위해서 다른 개발자와 reivew를 하고 승인이 되면 그 때 master branch로 반영이 되는 것이다.

release 시기가 되면별도로 release branch를 만든 후에, release에 필요한 각종configuration file 정리기타 메뉴얼이나 문서등을 합쳐서 release하고, release가 된 버전은 main branch에 반영한 후 tagging을 한다.

오픈소스 프로젝트에 보면소스 코드가 날짜나 버전 별로 open 이 되어 있는 형태를 본 기억이 있을 것이다이렇게 main branch는 외부 개발자 공개를 위해서 유지하고특별한 release가 있을때에만 반영하여항상 main branch에는 문제 없는 버전이 존재하도록 한다.

또한 혹시 main branch를 통해서 공개된 버전이 문제가 있을 경우에는 별도로 Hot fix (버그 수정용) branch를 만들어서 버그를 수정하고테스트를 끝낸 후에버그 수정 내용을 main branch에 반영하고 또한 함께, develop branch에도 반영한다.

 일반적인 소프트웨어 브렌치 관리 전략

다음은 git 이전에 많이 유행하였던, Subversion (이하 svn) 사용시 많이 사용하는 브렌치 구조이다. SVN에서는 크게 아래와 같이 세가지 브렌치를 메인으로 하여 코드를 저장하는 구조를 사용한다.



trunk 또는 head 라고도 하는데, 이 브렌치는 현재 개발이 진행중인 코드를 저장한다.

개발을 진행중에, 빌드나 또는 특정 날짜를 기준으로 tag를 따놓는데, 향후 빌드 실패나, 특정 날짜의 개발 내용으로 돌아가기 위해서 사용하며 이는 tags라는 브렌치 아래 들어간다. tag 명은 위의 그림에서와 같이 날짜를 사용할수 도 있으며, 또는 빌드 시스템의 빌드 #를 사용하기도 한다.

마지막으로 release 브렌치이다. Branches는 릴리즈시마다, 그 때의 소스코드 형상을 저장해놓는 구조이다.

이 브렌치 전략은 단일팀에서, 서비스나 제품을 릴리즈 주기를 통해서 릴리즈 하는 구조에 적절하며, 버그 수정이나 기능 개선은 다음 버전(release)에 포함 시키는 형태일 경우 적절하다. (별도의 패치를 위한 브렌치를 관리하는 전략이 없기 때문에)

8)   분산 형상 관리 시스템 Git

그러면 근래들어 많이 사용되고 있는 VCS 시스템인 Git에 대해서 알아보도록 하자.

Git는 기본적으로 분산 소스코드 관리 시스템이다. 모든 개발자가 중앙 저장소에 붙어서 작업을 하는 것이 아니라. 소스 코드가 여러개의 서버에 다른 복제본으로 존재할 수 있다. 먼저 이 분산 저장소의 개념부터 이해 해보도록 하자

중앙 집중형 저장소 (Centralized Version Control System)

중앙 집중형 저장소는, 코드가 저장 서버 단 한군데만 저장된다. 개발자가, 코드를 받아서 수정하고 저장하면, 그 내용이 바로 중앙 저장소에 반영된다 (당연 하지만). 즉 서버에는 항상 마스터 버전(최신 버전)의 소스코드가 저장되어 있다.

  그리고, 서버가 다운 되거나, 네트워크에 접속할 수 없다면 당연히 코드를 commit하거나 최신 코드를 내려받을 수 없다.



분산형 저장소 (Distributed Version Control System)

분산 저장소는 말 그대로, 소스코드가 하나의 중앙 서버가 아니라, 여러개의 서버나 여러개의 개발자 PC에 저장될 수 있으며, 각각이 소스 코드 저장소 (source repository)가 된다. 각 저장소에 저장되는 소스 코드는 같은 버전의 코드가 아니라 제각기 다른 브렌치 코드가 저장된다. 즉 서버 A에는 branch A,B,C 버전이, 서버 B에는 branch A,C,D버전과 같이 다른 브렌치 버전을 저장할 수 있다. 즉 각 저장소에 브렌치 버전이 모두 틀리고, 소스 코드를 access해서 가지고 오는 장소도 모두 다르기 때문에, 시스템 자체에서는 마스터 버전 (최신 버전이 항상 어느 곳에 저장되어 있는가)의 개념이 없다. 예를 들어 설명하자. 아래 그림과 같이 Developer Terry Server A에서 코드를 내려 받아서, 데이타 베이스 관련 모듈을 개발하고 있고, Michelle Server B에서 UI 관련 모듈을 개발하고 있다. 각자는 개발을 진행하면서, 수시로 각자 Server A Server B Commit을 하고 있다고 가정하자. Server A는 전체 시스템에서 데이타 베이스 모듈 부분은 가장 최시일테고, Server B에는 UI 모듈의 가장 최신 버전의 코드가 들어가 있을 것이다.

대신 각 모듈의 개발이 끝나면, Server A Server B의 코드를 merge하여, 개발 내용을 병합(합칠 수)할 수 있다.

즉 전체 시스템의 최신 소스 코드가 명시적으로 어느 한곳에 저장되어 있지 않는 구조이다.



이러한 형태로, 코드의 여러 버전을 여러 저장소에 분산해서 저장할 수 있기 때문에, 몇가지 장점이 올 수 가 있는데, 팀 단위나 기능 단위로 저장소를 분리해서 개발하거나 릴리즈 버전 단위로 저장소를 분리해서 개발할 수 있는 등 소스코드 버전관리에 많은 유연성을 가지고 있다.

또한 중앙 저장소의 개념이 없기 때문에, 특정 VCS 시스템이 장애가 나더라도, 내가 사용하고 있는 VCS만 문제가 없다면 개발을 계속할 수 있고, 앞에서 언급한바와 같이 개발자의 Local PC VCS를 설치하여 네트워크 연결이 없는 상태에도 개발을 지속할 수 있다.

그리고 소스코드가 중앙 서버만이 아니라 여러 서버와 PC에 분산 되서 저장되기 때문에 서버 장애로 저장소가 손상된다고 해도, 다른 서버나 다른 PC에서 소스코드와 History들을 모두 저장하고 있기 때문에, 중앙 서버 방식에 비해서 복구가 쉽다.

Git

DVCS Mercurial, Bazzar등 여러가지 제품이 있으나, 근래에는 git 가 가장 많이 사용되고 있다. Linux Kernel 프로젝트나, 안드로이드, Gnome, Ruby on Rails등이 Git를 사용하는 대표적인 프로젝트이다.

Git는 기존의 VCS에 비해서 설치가 쉽고, 속도가 매우 빠르다. 그리고, branch merge가 매우 빠르고 사용이 쉽다. 특히 merge의 경우 누가? 언제? 무엇을 어떤 부분을 merge했는지 까지 상세하게 추적이 가능하기 때문에, 오픈 소스와 같이 대규모 개발자가 동시에 개발을 진행하는 환경에서는 매우 유용하다. 오픈소스 개발자들이 network가 연결되어 있지 않은 상황에서도 언제 어디서나 개발을 할 수 있다. 그리고, 자기만의 개발 branch로 개발을 하다가 main branch merge도 쉽다. 아마 이런 장점이 git major VCS로 만든게 아닌가 싶다.

 

그러면 간단하게, git의 간략한 기본 사용법을 알아보자.



1)     Repository 생성 (init clone) - git에서 init 명령은 local에 새롭게 저장소를 만드는 명령이다. 이를 통해서 새롭게 git 저장소를 만들 수 있다.
만약에 원격에 있는 서버의 저장소를 복제해서 로컬에 만들려면
git clone
사용자명@서버주소:"저장소 경로"
명령어를 사용하면 된다.

2)     파일 추가
다음으로 파일을 추가해보자. 위의 예제에서 echo 명령을 사용하여, init.html, index.html 파일을 생성하였다. 그리고 git에 이 파일이 git commit이 될 예정이라고 mark를 해놓는다. 위의 예제에서는 index.html 파일만 먼저 commit을 하도록 한다.
git
에서는 add의 개념을 이해하려면 먼저 staging area라는 개념을 이해해야 한다.



작업 디렉토리 (working dir)에서 작업을 한것은 내 local pc에만 반영된 내용이다. 이 내용을 저장소로 올리기 전에, git staging(git에서는 index라는 이름으로 사용한다.) 이라는 개념을 제공한다. 소스 코드를 저장소에 최종 반영하기 전에 두 단계를 거치는 two-phase commit을 사용한다.

staging이라는 개념은 작업 디렉토리에서 작업한 내용을 반영하기 전에, 최종으로 확인하는 중간 단계 정도로 생각하면 된다. 작업 디렉토리에서 작업한 내용 중 commit할 내용을 미리 "add" 명령어를 통해서 stage에 반영한 후에, stage에 있는 내용을 commit전에, 저장소내의 코드와 비교(diff)하면서, commit을 할 수 있다.

작업 영역과 (working directory) stage영역간의 비교는
"git diff"
명령어를 통해서 가능하고  stage master 버전에 저장된 코드의 변경 사항은"git diff --cached"  (또는 git diff --staged) 명령을 이용해서 비교가 가능하다.

작업 디렉토리에서 바뀐 내용을 몽땅 한꺼번에 commit하는 것이 아니라, feature별이나 특정 그룹 (기능이나 FIX별 또는 모듈별)staging에 이동 시킨후, 하나하나 검증하면서 그룹별로 commit이 가능하다.

3)     저장소에 반영 (commit)
add
를 통해서, 변경본 반영 리스트를 작성하고, diff등을 통해서 확인이 끝나면, 이를 저장소에 반영해야 한다. 반영은 commit 명령어를 사용하며, commit에 대한 comment (변경 내용)을 같이 넣는다.
git commit -m "
변경 내용 description"

4)     변경 내용을 원격 저장소에 반영 (push)
앞 단계 까지 끝났으면, 소스코드의 변경 내용은 내 local pc에 있는 git 로컬 저장소에 반영되었다. git는 앞서도 설명했지만 분산저장소이기 때문에, commit을 한다고 해서, 서버에 코드가 저장되지 않는다. 기본적으로 commit은 로컬 저장소에 반영이 되지만, 서버의 원격 저장소에 코드를 반영하려면 별도의 반영 작업이 필요하다. 반영은 push 명령어를 사용한다. 다음과 같이 push 명령을 사용하여, 원격 서버에 반영한다.



git push origin "브렌치명"
) git push origin master (master branch push하는 명령)
※단 이 경우는 처음에 저장소를 만들때, git clone을 통해서 원격 저장소로 부터 코드를 읽어와서 로컬 저장소를 만들었을 경우이다.

만약에 원격 저장소로 부터 clone을 해서 만든 경우가 아닐때, 원격 저장소로 code를 밀어 놓고자 한다면, 원격 저장소를 정의해줘야 한다. 원격 저장소를 정의 하는 방법은
git remote add "
원격저장소명" "원격저장소주소"
) git remote add zipkin https://github.com/twitter/zipkin.git
zipkin
이라는 이름으로 https://github.com/twitter/zipkin.git URL에 있는 원격 저장소를 등록하였다. 여기에 push를 하려면, git push zipkin master (zipkin 원격 저장소 master branch push)

분산 저장 VCS 답게, 원격 저장소는 하나가 아닌 여러 개를 git remote add 명령을 통해서 추가 할 수 있고, 등록되어 있는 원격 저장소는 git remote -v 명령을 통해서 조회해볼 수 있다.

5)     브렌치 관리
소스코드 브렌치에 대한 개념은 앞에서 설명하였기 때문에 별도로 설명하지 않고, 명령어 사용법만 설명한다. 현재 코드에서 브렌치를 생성하려면

git branch "브렌치명" 을 사용한다..
) git branch bugFix
bugFix
라는 이름으로, 현재 코드에서 branch 만들기

그리고 현재 작업중인 브렌치를 이동하려면
git checkout "
브렌치명" 을 사용한다.
) git checkout master
master
브렌치로 이동

6)   merge

merge는 다른 브렌치의 내용을 현재 작업 중인 브렌치로 합쳐 오는 작업이다.
예를 들어 내가 master 브렌치에서 작업을 하고 있을때, 예전에 버그 수정을 위해 만들었던 bugFix라는 브렌치의 내용을 현재 브렌치에 반영하고 싶을 경우, master 브렌치에서 "git merge bugFix" 라는 명령을 사용하면 bugFix 브렌치의 변경 내용을 master 브렌치에 반영하게 된다.

이 때, 서로 변경 내용이 다르거나, 같은 코드 라인을 수정하였을 경우 충돌 (conflict)이 발생하는데, 충돌이 발생한 경우, 직접 충돌 부분을 수정한 후, git add를 통해서 수정한 파일을 넣고, git commit을 통해서 최종 반영한다.

7)   원격 저장소의 변경 내용을 읽어오기 (pull & fetch)

반대로, 원격 저장소에서 다른 사람들이 작업했던 내용을 내 로컬저장소로 가지고 오려면 pull fetch 라는 두 가지 방법이 있다.

먼저 fetch ("git fetch")의 경우, 원격 저장소의 업데이트 된 내용을 별도의 브렌치로 읽어 온다. 실제 내가 로컬에서 작업중인 로컬 저장소에는 반영되지 않는다. 반영을 하려면 원격 저장소에서 읽어온 내용을 merge를 통해서 내 작업 영역에 반영해야 한다 이해를 돕기 위해서 아래 그림을 보자.



원격 저장소의 v1 버전에서 clone을 받아서 로컬 저장소에서 개발을 시작하였다. 로컬에서 여러번의 commit을 통해서, v4 버전까지 개발을 진행하였다.

그 상태에서, 원격 저장소의 변경 내용을 업데이트 하기 위해서 fetch를 하면, 원래 clone을 하였던 원격 저장소의 브렌치 (master)의 최신 코드를 로컬로 복사해서 origin/master라는 이름의 브렌치에 업데이트를 한다. 내 작업 영역은 여전히 v4이고, 원격 저장소의 변경 내용은 반영되지 않았다.

이를 반영하려면 "git merge origin/master"를 해주면 merge를 통해서 내 작업 영역에 반영된다. (v5 버전상태)

pull ("git pull")은 한마디로, fetch + merge. pull 명령어 하나로 자동으로 fetch merge를 한꺼번에 해주는 명령어 이다. 아래 그림을 보자, 처음에 원격 저장소에서 v1 버전을 clone으로 내려 받아서 개발을 하다가, v4 버전에서 원격 저장소의 코드를 pull 해주면, 원격 저장소의 clone을 한 원본 저장소와, 로컬의 저장소의 현재 브렌치를 merge하여 새로운 버전으로 만들어 준다.



8)   태깅

git에서 태깅은 매우 간편하다.

git tag -a "태그명" -m "태그 설명"

) git tag -a "build1109" -m "July.15 빌드 태그".

태깅한 버전으로 이동하려면, 브렌치 이동과 마찬가지로 checkout을 사용하면 된다.

git checkout "태그명"

만약 그 태그 버전으로 부터 무엇인가를 작업하려면, 해당 태그로 이동한 후에, git branch를 이용하여, 그 버전에서 부터 branch를 따서 작업을 하거나 clone등을 해서 작업을 하는 것이 좋다. 그리고, 태그를 다른 사람과 공유하려면, 브렌치나 코드와 마찬가지로, 태그를 서버로 push해줘야 한다.

git push origin "태그명"

9)   Rebase

git rebase git만의 고유 기능이다. merge와 유사한 기능이지만, 코드 변경 History를 조금더 깔끔하게 정리해주는 기능이라고 생각하면 된다.

다음과 같은 브렌치가 있다고 하자. V3에서 브렌치를 생성하여 V4를 만들어내었고, master에서는 commit을 진행하여 V5로 진행되었다고 하자. 이 상태에서 V4의 변경 내용을 V5로 합치고자 한다.



일반적인 경우에는 merge를 한다. 아래와 같이 merge를 하는 경우에는 V6 버전이 새로 생기고, V4 branch와 내용과 history가 모두 유지 된다.



반면 rebase 명령을 수행할 경우, merge와 마찬가지로, 코드를 master branch로 합치지만, 기존의 V4 branch는 없어지고, V4에 작업된 내용 (변경 History)는 마치 master branch의 변경 history인 것 처럼 하나로 합쳐진다.



유용한 git 관련 도구들

git의 경우, 요즘 널리 사용되는 만큼 지원되는 도구들도 많다. 여기서 몇몇 유용한 git 지원 도구들에 대해서 살펴보도록 하자.

1)   git-gui & gitk

이 두가지 툴을 gui 툴로, git를 설치하면 기본적으로 설치 된다. git-gui git에서 commit을 하는 것을 도와주고, gitk git 저장소를 gui 기반으로 browsing할 수 있게 해준다.  

2)   gerrit

gerrit는 오픈소스 코드리뷰 도구로 (https://code.google.com/p/gerrit/) 에서 다운로드 바을 수 있으며, git를 사용시, 웹 기반으로 코드 리뷰를 가능하도록 해준다.

master branch dev branch를 갖는 상태에서, dev branch에서 개발을 한 후, dev branch push를 하면, jenkins등과 같은 자동 빌드 도구에서 컴파일 및 테스트를 수행한 후에, gerrit을 통해서 코드 리뷰 요청을 생성하고, 코드 리뷰어가 리뷰를 끝내면, 코드를 master push하는 시나리오를 만들 수 있다. UI는 좀 떨어지긴 하지만, 저렴한 비용으로 코드리뷰 도구를 사용할 수 있다.



3)   gitLab

git lab 역시 오픈 소스이다. 코드 리뷰뿐만 아니라, git 저장소에 대한 browsing, 프로젝트 관리, 이슈 관리등 다양한 기능을 제공한다.



지금까지 git에 대해서 가장 기본적인 기능만을 소개하였다. 이외에도 상당히 많은 기능이 있기 때문에, git의 경우에는 꼭 별도의 서적을 참고해 보기를 권장한다.
Pragmatic Version Control Using Git, 저자 Travis Swicegood , ISBN-10: 1934356158
※ 참고할만한 글

Ÿ   git에 대해서 간략하게 설명해놓은 문서http://rogerdudler.github.io/git-guide/index.ko.html

Ÿ   git에 대해서 설치 없이 간단하게 배울 수 있는 온라인 튜토리얼
http://pcottle.github.io/learnGitBranching/

사실 git를 사용해보면,그 속도도 빠르고 branch 생성이나 merge도 쉬워서 참 유연한 툴이구나 생각하게 된다. 반대로 생각해보면 유연하다는 것은 사용할 수 있는 용도가 많다는 것이고, 잘 모르면 어떤 방향으로 사용해야 할 지 정하기가 매우 애매하다는 이야기가 된다. svn과 같은 경우는 일반적으로 사용하는 branch 전략이 정해져 있어서 learning curve도 낮아서 쉽게 사용할 수 있지만, svn과 같은 centralized VCS에 익숙해져 있는 사람은 git를 접하면 개념을 잡는데 한참 시간이 소요되다가, 결국은 centralized VCS와 같은 형태로 사용하는 경우가 종종 있다.

 git가 되었건, svn이 되었건 간에, 툴의 사용법 보다는 소스코드의 버전 관리의 본질을 제대로 이해하고, 팀과 프로젝트 성격과 회사내의 릴리즈 정책에 맞는 VCS를 선택하고 그에 맞는 브렌치 전략을 제대로 수립하고 적용해 나가는 것이 더욱 더 중요하다.  특히 조직의 규모가 커지면 커질 수 록, 그리고 릴리즈하는 버전의 다양성이 많을 수 록, 효과적인 브렌치 구조의 정의는 개발 환경의 효율성에 아주 지대한 영향을 미치게 된다.

또한 이 글을 쓰는 내내 머릿속에 멤도는 생각은 수년전만 해도 개발자가 사실 이러한 VCS branch 전략에 대해서 크게 신경 쓸 필요가 없었다. 일반적인 팀 단위 프로젝트에 들어가서 Check out, update, commit, merge 정도만 잘하면 되었으니까는, 그러나 앞서서 git에서 살펴보았듯이. 이미 소스 코드 관리 전략은 오픈소스등의 영향을 많이 받아서 분산형이 대세다. 분산을 하다보니, 상대적으로 다른 개발자나 개발팀의 간섭을 덜 받으면서 별도의 브렌치에서 작업을 해서 코드 작업을 할 수 있다는 장점도 있지만, 그만큼 개발자가 이제는 코드 관리에 대한 깊숙한 이해를 가져야 한다는 것이다

그리드형

'ALM > SCM/VCS' 카테고리의 다른 글

github 연동 방식 메모  (0) 2014.01.12
Git branch reference  (0) 2013.06.25
git 기본 command  (0) 2013.06.24
VCS 브렌치 관리 전략  (0) 2013.05.27
git 노트  (0) 2013.05.27