참고문서 : [GIT] GIT이란 무엇인가, GIT에 대하여 , [웹개발 기초] Git 이란?
대학교 때 과제, 프로젝트 등을 진행하며 '협업 코딩'을 할 때 이런 경험이 있을 것이다.
" 여기까지 코딩하고 메일로 보내면 내가 다시 수정할게 "
" source_진짜진짜최종.py 열어보면 돼 "
학부에서 수행하는 1~2명 규모의 과제, 프로젝트는 최종 결과물만 제출하면 종료되고 이후 별도의 소스관리를 할 필요가 없기에 위 대화와 같은 관리 방식으로도 관리 가능하다.
하지만 기업 실무에서 수행되는 프로젝트는 다르다. 대개 수십명~수백명이 프로젝트의 구성원으로 참여하고, 프로젝트 종료 후에도 소스코드의 지속적인 유지보수가 이루어지므로 체계적인 관리가 필요하다.
그렇다면 소스 관리를 어떻게 해야할까?
해답은 GIT 에서 찾을 수 있다.
형상 관리 도구란?
형상관리는 소스의 변화를 지속적으로 관리하는 것을 말한다.
소프트웨어 버전 관리 시스템이라고도 한다.
대표적으로 SVN과 GIT이 있다.
SVN : 중앙 서버에 소스코드와 히스토리를 저장하는 중앙집중식 버전 관리 시스템(CVCS)
Git : 소스코드를 여러 개발 PC와 저장소에 분산해서 저장하는 분산 버전 관리 시스템(DVCS)
git과 svn 방식의 차이 (그림 출처: https://dzzienki.tistory.com/46)
자세한 차이는 아래 블로그에 잘 정리되어 있으니 한 번 읽어보면 좋다.
높은 생산성 : 소스코드 주고받기가 필요 없고, 같은 파일을 여려 명이 동시에 작업 가능하며, 버전 관리가 용이하다.
체계적인 변동 관리 : 소스 수정사항이 커밋 단위로 관리되고, 패치 형식으로 배포 가능하며, 이전 시점의 소스코드로 쉽게 점프(Checkout) 가능하다.
빠른 속도 : 각각의 개발자들이 모두 분산처리 서버의 주인이 되는 셈이므로 서버가 직접 해야 될 일들이 많이 줄어든다.
안전성 : 신규 기능을 추가하는 Experimental version을 개발하는 경우, 브랜치 내 충분한 테스트 후 본 프로그램에 합치는 방식(Merge)으로 개발을 진행할 수 있다.
유연성 : 서버와 클라이언트 뿐인 기존 형상관리에 비해 분산처리 구조를 유연하게 세울 수 있다. 중간 서버를 구축하거나, 부서별로 따로 서버를 구축하는 등 자유로운 구성이 가능하다.
오프라인 작업 가능: 분산 버전 관리이므로 인터넷이 끊겨도 로컬저장소 기준으로 형상 관리가 가능하다.
git의 transaction (그림 출처: http://pismute.github.io/whygitisbetter/)
위 이미지는 GIT의 주요 트랜잭션을 정리한 도표이다.
이를 한 줄로 나타내면 다음과 같다.
- "작업한 내용을 스테이징에 올려서 로컬 저장소에 커밋하고, 이를 푸시해서 원격 저장소로 보낸다."
소스코드가 저장된 여러 개의 브랜치(Branch)들이 모여 있는 디스크상의 물리적 공간을 의미한다.
GIT에서는 저장소가 로컬저장소(Local Repository)와 원격저장소(Remote Repository)로 나뉜다.
특정 시점이나 브랜치의 소스코드로 이동하는 것을 의미한다.
체크아웃 대상은 브랜치, 커밋, 그리고 태그다. 체크아웃을 통해 과거 여러 시점의 소스코드로 이동 가능하다.
작업한 내용을 로컬저장소에 저장하는 과정이다.
각각의 커밋은 의미 있는 변경 단위이고, 변경에 대한 설명을 커밋 로그로 남긴다.
커밋한 소스는 로컬저장소에 저장되며, 푸시(Push)까지 진행해야 원격 저장소에 반영된다.
프로젝트 팀에 따라 커밋의 단위가 서로 다르고, 커밋 로그를 작성하는 형식(Format)도 정해져 있다.
커밋의 임의 위치에 쉽게 찾아갈 수 있도록 붙여놓은 이정표를 태그라 한다.
태그가 붙여진 커밋은 Commit ID 대신 태그명을 입력하여 쉽게 체크아웃 가능하다.
SVN에서의 커밋은 변경 사항을 원격저장소로 저장하는 과정을 의미한다.
GIT에서의 커밋은 로컬저장소로 변경 사항을 반영하는 것을 의미하며, 원격저장소로 변경사항을 보내는 과정은 푸시다.
- 'SVN의 커밋 = GIT의 커밋 + GIT의 푸시' 라고 할 수 있다.
푸시와 반대로 원격저장소의 내용 중 로컬저장소에 반영되지 않은 내용을 가져와서 로컬저장소에 저장하는 과정을 의미한다.
이를 통해 다른 팀원이 변경하고 푸시한 내용을 내 로컬저장소에 반영 가능하다.
충돌(Collision)로 인해 푸시가 거절된 경우, 풀을 통해 원격저장소의 변경 내용을 반영한 뒤 다시 푸시를 시도해야 한다.
git의 branch (그림 출처: https://gmlwjd9405.github.io/2018/05/11/types-of-git-branch.html)
브랜치 중에 개발의 주축이 되는 브랜치를 마스터 브랜치(Master Branch)라 하며, 모든 브랜치는 마스터 브랜치에서 분기되어 최종적으로 다시 마스터 브랜치에 병합(Merge)되며 개발이 진행된다.
브랜치를 항상 마스터 브랜치에서 해야 한다는 제약은 없으며, 브랜치에서 다시 브랜치를 할 수 있다.
대개 프로젝트에서 브랜치는 프로그램 전체를 몇 개의 단위로 나눈 토픽 단위로 생성하며, 각 토픽 브랜치에서 개발자별로 새로운 브랜치를 생성하여 작업을 한다.
개발자별로 작업한 내용은 토픽 브랜치에 병합되며, 최종적으로 마스터 브랜치로 병합되어 하나의 토픽이 종료된다.
- Master Branch : 제품으로 출시될 수 있는 브랜치
- Develop Branch : 다음 출시 버전을 개발하는 브랜치
- Feature Branch : 기능을 개발하는 브랜치
- Release Branch : 이번 출시 버전을 준비하는 브랜치
- Hotfix Branch : 출시 버전에서 발생한 버그를 수정하는 브랜치
각 브랜치 별 차이는 아래 블로그에 잘 정리되어 있으니 한 번 읽어보면 좋다.
브랜치와 반대되는 개념으로, 하나의 브랜치를 다른 브랜치와 합치는 과정을 의미한다.
두 개의 브랜치를 합쳐서 하나의 브랜치로 만드는 3-Way Merge가 모든 병합 작업의 기본이 된다.
병합 대상이 되는 두 브랜치는 주종관계가 성립하여 'A브랜치를 B브랜치에 병합'하는 작업과 'B브랜치를 A브랜치에 병합'하는 작업은 서로 다른 작업이다.
병합은 '서로 다른 두 커밋으로부터 하나의 새로운 새로운 커밋을 생성하는 작업'입니다.
병합 과정에서 두 개의 브랜치에서 파일의 같은 부분을 서로 다르게 수정한 경우 충돌(Collision)이 발생하며, 병합이 일시정지 된다.
병합은 주로 Project Manager(PM)이 일괄로 수행한다. 한 브랜치의 작업이 끝나면 PM에게 Merge Request를 요청하고, PM은 해당 브랜치를 작업한 개발자와 함께 코드 리뷰 진행 후 이상이 없으면 마스터 브랜치에 해당 브랜치를 병합한다.