본문 바로가기

개인개발

[소스관리, Git] 레벨2 - 두 사람이 개발할 때 소스는 어떻게 저장하나요

지난시간: http://stanleykou.tistory.com/entry/Git-레벨1-내-PC에-저장하지-말고-git에-저장하기



지난시a간에는 Git 세팅과 기초적인 사용법을 다뤘습니다.


요약: 파일을 Git에 저장하려면 Add, Commit 하고나서 인터넷의 저장소( Repository)에 Push 하세요!


이번 시간에는 조금 더 나가서, 실제 프로젝트에서 Git을 어떻게 쓸 수 있고

왜 Git을 써야 하는지 알아보겠습니다.


레벨 3에서는 좀 더 다양한 Git 의 활용방법, "브랜치"를 알아보기로 하고, 레벨 2 시작합니다.




왜? 이걸 쓰나?


소규모 프로젝트를 예로 들어 보도록 하죠.


대학교의 텀프로젝트인데 3인 1팀으로 개발하게 되었습니다. (모두 의욕에 충만하며, 이탈자는 없고, 협조적으로 개발하고 있는 이상적인 상황을 가정합시다. 너무 이상적인 상황이지만, 지금 포커스는 "개발"이니... )


프로그램 하나를 만들어야 하니, 이걸 파트별로 3명이 개발하기로 합니다.


소스를 어떻게 관리해야 할까요? 단계별 진화과정을 보시겠습니다.



1. 주먹구구식


순차적으로, 한 사람이 작업을 먼저 하고, 그걸 복사해서 모두에게 전달합니다.

그러면 두 번째 사람이 작업을 하고, 다시 그걸 복사해서 다른 모두에게 전달합니다.


그러면 한 사람이 작업하는 동안 다른 두 사람이 아무일도 못하고 기다려야 합니다.


시간낭비군요. 이건 아닌 것 같으니, 다른 방식을 찾아야겠죠.



2. 동시작업


큰 골격을 일단 잡아 놓습니다. 그리고 각자 맡은 파트를 개발하고, 자기가 작업한 내용을 복사해서 메일로 전체 공유합니다.


프로젝트-A.zip, 프로젝트-B.zip, 프로젝트-C.zip 세 개의 파일이 생기네요.


프로젝트가 끝날 때 쯤 프로젝트-A-250번째.zip, 프로젝트-B-347번째.zip, 프로젝트-C-113번째.zip 파일이 나왔습니다.


그런데 이걸 합쳐보니 컴파일이 안됩니다. 어디서 부터 안된 걸까요?

확인 해 보니 프로젝트-A-24번째.zip에서 인터페이스를 수정해서 쓰고 있었고, 그것이 다른 프로젝트에는 들어가지 않았습니다.


세 파일을 합치는데 3일이 걸렸고, 이건 아닌 것 같다는 것을 깨달았습니다.



3. 차라리 제일 쉬운, Git


git을 처음 써 보면 낯설고 어렵게 느껴질 수 있습니다.

하지만 쓰다보면 "아, 이거 없었으면 지옥같았겠다"는 생각이 들겁니다.


무거운 도끼는 거추장스럽지만 나무꾼이 나무를 벨 때 무거운 도끼가 아닌 맨손으로 나무를 베려고 하면 지옥을 맛보듯, git이 처음에는 거추장스럽더라도 나중에 쓰다보면 왜 다들 이걸 쓰는지 자연스럽게 동의하게 될겁니다.


자, 이제 git으로 소스를 형상관리 하며 진행합니다.


- A가 개발을 완료하고, 자신의 작업물을 git에 올립니다. (Add, Commit, Push)


- B, C는 작업을 하기 전에 먼저 Git 에서 소스를 다운로드 (Pull)을 받습니다.


- 그러면, "자동으로 내 로컬 PC의 소스에 A의 작업물이 합쳐집니다"!!! 마술이죠!


- B는 신규 소스에서 작업하고, 자신의 작업물을 git에 올립니다. (이 과정을 앞으로는 "커밋한다" 라고 말하겠습니다


- 그런데 C는 실수로 신규소스를 다운로드 받지 않고 작업했습니다. 그리고 커밋을 하려고 하니 에러가 나옵니다. 그러면, 그냥 소스를 다운로드(Pull)을 받습니다. 그러면 자동으로 신규 수정사항이 내 소스에 적용됩니다.


- 그 다음 C가 최신소스가 된 자신의 소스를 커밋합니다.





직접 해보자!


1. 차라리 제일 쉬운 Git, 만약 소스가 "충돌(Conflict)"한다면?


3번과 같이 git을 쓰더라도, 만약 "공통으로 쓰는 부분을 서로 다른 여러 작업자가 수정했다면" 에러가 발생할 수 있습니다.


예를 들면, 아래와 같은 경우 말이죠.



처음 소스


print ("Hello World") 



A가 수정한 내용:


print ("Hello World A") 



B가 수정한 내용:


print ("Hello World B") 



C가 수정한 내용:


print ("Hello World C") 



이 세 소스를 커밋하면 어떻게 될까요? 같은 파일의 같은 라인을 서로 다르게 수정했습니다.


이 때는 일단... 시간 상으로 제일 먼저 커밋한 것은 문제없이 커밋됩니다.


그런데 두 번째와 세 번째 것의 경우, Conflict가 발생합니다.



Conflict!


Conflict가 발생하면 소스 파일에 텍스트 파일로 아래와 같이 기록됩니다.


<<<<

// Git에 있는 내용

====

// 현재 PC에 있는 내용

<<<<



그 때는 당황하지 말고, 내용을 찬찬히 살펴봅니다. 어떤 내용이 들어가야 하고, 어떤 내용이 빠져야 하는지 수작업으로 수정합니다. 


그리고 나서 컴파일 되는지 확인 한 뒤, Add, Commit, Push합니다.




2. git의 유용함 - 히스토리 관리


하나의 작업이 완료될 때 마다 git에 커밋을 하고, 코멘트도 충실하게 남깁니다.


그러면 git이 그 진가를 발휘하게 되는데, 그건 바로 히스토리 관리입니다.


bitbucket에 들어가 봅시다. 그리고 Repository를 고른 다음, 좌측 메뉴 중 "Commits"를 선택합니다.



Commits



이 때까지 작업한 내용입니다. 캡쳐에는 안나왔는데 날짜도 나옵니다.

즉, 언제 누가 어떤 작업을 했는지 모두 기록됩니다. 


만약 이런일이 있다면 어떨까요?

"어, 이거 언제 바꿨었지? 이 부분만 다시 원래대로 돌아가려고 하면 어떻게 해야되지?"


(레벨 2에서는 복잡한 git 기능 활용 안하겠습니다. 간단히 해당 부분을 수작업으로 바꾸고 새로 커밋하겠습니다.)


commit 번호가 파란색 링크로 표시된 것이 보이실 겁니다. 그걸 클릭 해 보세요.





짜잔! 내가 수정한 내역이 나옵니다. 그것도 라인바이 라인 비교를 보여주기까지 합니다.


즉, 내가 코딩하다가 실수로 잘못된 내용을 저장해도, 모든 기록이 남아있기 때문에 그 이전으로 돌아갈 수 있게됩니다.


만약 로컬 PC에서만 작업을 했다면 어떨까요?


"아, 내가 이거 언제 고쳤지?"

"하루에 한 번 전체 파일을 백업하기는 하는데... 압축해 놓은거라 압축을 풀어서, 수정했던 것으로 추정되는 파일을 찾아서, 현재파일과 비교를... "


하지만 git을 쓰고 있다면, 간단히 몇 번 클릭하는 것 만으로 언제 어떤 수정사항이 있었는지 확인할 수 있습니다. (물론 수정량이 많다면.... OTL 그러니 커밋은 비교적 작은 작업을 하나의 단위로 묶는 걸 추천합니다)





정리하면,


git을 이용하면 여러명이 개발할 때 편리하게 작업할 수 있습니다.


그리고 히스토리 관리 기능을 이용해서, 언제 누가 어떤 수정을 했는지 편리하게 찾아볼 수 있습니다. (실은 회사에서 형상관리 시스템을 쓰는 이유도 이게 핵심입니다)


개발자들이 모두 git 초보자라면, 고급 기능을 이용하지 않고 "잘못된 코드를 발견하면 (1) 최신소스를 받고 (2) 잘못된 코드를 수정해서 새로 커밋" 만 해도 충분히 잘 개발할 수 있습니다. (SVN이 이런 "직선형" 개발방식입니다)





다음 단계에서는,


브랜치에 대해서 알아보겠습니다.

과거에 많이 이용되던 SVN 과 비교해서, git의 가장 혁신적인 기능입니다. 


한 마디로 설명하자면... 다양한 버전의 프로그램을 만들어야 할 때 "브랜치"를 생성하여 작업하면 각각의 버전을 구분할 수 있게 되는 겁니다. 


"직선형" 인 SVN이 아닌, "가지가 뻗어나가는" 형태의 git 의 진가를 느끼려면 브랜치를 꼭 써봐야 합니다. 이 때, "뻗어나간 가지"인 브랜치는 다른 브랜치에 합칠수도 있고, 일부를 떼어내 다른 곳에 넣을 수도 있고, 수정사항 일부만 가져다가 다른 브랜치에 적용할 수도 있는 등 매우 다양하고 유용한 기능이 가득합니다.



더불어 특정 파일이 어떤 커밋으로 구성되어 있는지 보여주는 "blame" 기능에 대해 알아보도록 하죠.

한 파일에 라인 별로 "이 라인은 a123456 커밋에서 A가 추가함", "이 라인은 a123457 커밋에서 B가 추가함" 이렇게 알려주는 기능입니다.