Git 브랜치의 이해
branch 란 ?
- 본래의 소스코드로부터 파생한 독립적인 작업 공간이다.
- 최신 커밋을 가리키는 일종의 포인터이다.
- 매우 가볍고, 생성-이동-병합이 매우 쉽다.
- 브랜치는 나눠서 사용하는 것은 해당 SW 개발팀의 전략이라고 할 수 있다.
- 브랜치는 목적에 다라 분기가능하고, 전략은 조직에 따라 달라진다.
master 브랜치
- Git은 기본적으로 먼저 master 브랜치를 생성하고 시작하게 된다.
Git Branch 실습
> 처음 git brnach 명령어를 입력하면 아무것도 뜨지 않는다.
> master 브랜치는 첫 커밋이 생성되어야 포인터로 그 커밋을 가리키게 된다.
> 새로운 커밋을 반영하여 addm commit 한 뒤 git branch를 입력해보자
> 새로운 master branch가 생성된 것을 확인 할 수 있다.
> "master branch는 첫 번째 commit이 생성되어야 포인터를 가리킬 수 있다."
HEAD
- 현재 브랜치를 가리키는 포인터이다.
- 마지막 커밋에 대한 스냅샷이라고도 한다.
- [ HEAD ] ==> [ master ] ==> [Commit1]
위의 실습에 의해서 현재 commit1 의 내용이 commit2로 업데이트 된 것을 알 수 있다.
이 때 깃은 두 번째 커밋에 대해서 branch와 Head의 포인터가 연쇄적으로 이동하게 된다.
깃의 흐름을 보면 아래와 같이 도식화하여 나타낼 수 있다.
> master branch가 commit의 포인터를 갱신할때 마다 새로 할당하게 된다.
브랜치의 분기
> 브랜치는 목적에 따라 분기할 수 있다.
> 이는 기능 개발을 하는데 용이하게 한다.
> 아래 그림과 같이 master 브랜치에서 login을 구현하는 branch를 생성 할 수 있다.
브랜치 생성
$git brnach "생성할 브랜치 명"
위의 명령어를 통해 새로운 branch를 생성할 수 있다.
$git branch
$git log
현재 브랜치의 상황을 보면 다음과 같다.
브랜치의 이동
$ git checkout "이동할 브랜치명"
checkout이후 Head는 feature-login의 포인터를 가리키게 된다.
흐름을 살펴보면 아래와 같이 실행될 것이다.
즉 checkout은 HEAD가 어떤 값의 포인터를 가리키는지 변하게된다
실습
위의 코드를 분석하면 feautre-login branch는 "3번째 커밋"을 완료했고, master branch에는 방금 전과 같이 "2번째 커밋"이 되어있는 상태이다.
깃의 브랜치의 흐름을 보면 다음과 같이 나타낼 수 있다.
- 현재 상황에서 각 브랜치는 독립된 저장물들을 가지고 있다.
- master에는 commit 2 이므로 LoginService.java 파일이 존재하지 않는다.
- feature-login 에는 모든 파일이 존재하게 된다.
브랜치 이동(CHECKOUT) 정리
- HEAD는 checkout 대상 브랜치로 이동하게 된다.
- 로컬저장소의 상태에서는 HEAD가 가리키는 마지막 커밋이 최신이 된다.
- 작업 디렉토리의 파일 상태는 변경된다.
- 즉 checkout은 HEAD가 가리키는 포인터를 변경시킨다.
위의 상황에서 git checkout master를 통해 master 브랜치로 이동한 뒤,
새로운 "commit #4"를 작성하고 log를 살펴보면 어떻게 될까?
당연히 master는 commit3을 가지지 않아서 commit1,2,4만 출력되게 된다.
(commit3은 feature-login branch에 존재하고 여기에는 commit 4가 존재하지 않음)
branch 생성 동시에 checkout
$ git checkout -b issue
$ git branch
master
feature-login
* issue
- issue라는 branch를 생성함과 동시에 checkout 하는 명령어 ( -b 옵션 )
- branch 명령어를 통해 branch 상태를 확인
- 이 때 HEAD 포인터는 issue라는 branch의 포인터를 가지게 된다.
- 하지만 issue는 commit을 가지지 않기 때문에 issue는 아무것도 참조하지 않는다.
- 여기서 새로운 커밋을 생성하면 각 branch와 커밋은 어떻게 되는지 알아보자
다음의 코드를 통해 MainService.java 파일이 수정되어서 새로운 변경점이 생기고 add -> commit을 통해서 새로운 버전을 생성한다.
정리하면 5번째 커밋이 issue branch에서 커밋되었고, 이 는 issue branch에만 적용된다.
그림으로 도식화하면 아래와 같다.
Branch 병합
이전까지 이슈가 발생한다면 원래의 branch에서 issue의 해결을 위해서 새로운 branch를 생성하고 그 부분을 branch 내에서 수정하고 커밋하는 방법에 대해 살펴보았다.
이제 우리가 모든 issue를 해결하였다면 원래의 주 branch로 돌아가서 이 작업 내용을 옮겨야한다, 즉 branch#1 과 branch#n 이 결합해서 이슈에 대한 수정본이 완성되는데 이때 수행하는 것을 branch 병합이라고 한다.
git merge
(1) 기준이 되는 브랜치로 이동해서 병합해야 한다.
- issue branch --> master branch
- $git checkout master를 통해서 HEAD 포인터 위치를 바꾼다
(2) 합쳐질 브랜치를 명시하여 merge를 통해 병합한다 ( 기준 : 현재 속한 branch )
- $git merge issue
- 다음의 명령어를 통해 현재 branch( master )에 issue를 합치게 된다
(3) master branch에 issue branch를 병합시킨다.
Fast-forward Merge
> branch의 위치만 최신 커밋으로 이동시키는 방식을 의미한다.
> 이 때 2개의 브랜치가 중복된 커밋 변경점을 가지므로 하나의 브랜치는 삭제하는 것이 좋다.
> 브랜치를 삭제하는 명령어는 아래와 같다.
$ git branch -d issue
Deleted branch issue (was d73244b(
> 브랜치를 삭제한 후 git log , git branch -v 로 확인하면 더 이상 issue branch가 나타나지 않는다.
> 깃에서 branch를 삭제한다면 issue의 포인터 (commit 5를 가리킴)가 삭제되므로 삭제가 쉽고, 빠르다.
3-Way Merge
특정 조건에서 3가지의 commit 버전을 합치는 방법을 말한다.
조건은 어던 기준점에 대해서 나뉜 두 버전이 서로 다른 수정 내용을 가지고 있을 때 발생한다.
3가지 커밋
1) master와 feature-login 브랜치의 공통 부모 커밋
2) master 브랜치의 최신 커밋
3) feature-login 브랜치의 최신 커밋
Git의 브랜치 병합은 항상 성공하지 않는다.
서로 병합하는 브랜치 사이 파일이 동일하지 않는 경우, 어떤 버전으로 수정해야 하는지 알지 못하기 때문이다.
이를 변경사항의 충돌이라고 한다.
Conflict ( 변경 사항 충돌 )
git은 항상 병합(merge)에 성공할까?
- 정답은 아니다. 깃의 버전의 흐름 사이 다른 변경점이 있는 경우 충돌이 발생한다.
- 어떤 변경사항을 반영할지 결정하여서 반영해야 한다.
- 직접 merge 하는 방법 , Tool을 이용해 merge하는 방법 2가지가 존재한다.
해결방법
1) 직접 merge
직접 충돌 파일을 수정하여서 merge한뒤 커밋하는 방법
2) mergetool 사용하기
$ git mergetool
<오류 발생 시> $git config merge.tool vimdiff
> 각 변경점, 공통부모들을 확인하면서 아래에 MainService 파일을 수정할 수 있다.
> 3-Way merge를 사용하므로 총 3개의 상위 창들이 생성된다.
> 완료된 병합 커밋은 아래와 같은 흐름을 가지게 된다
Tag
tag
- 특정 branch위에서 생성되어 특정 시점의 소스코드 정보를 기록히는 것을 의미한다.
- 프로젝트 진행중 의미있는 시점의 커밋을 태깅한다.
- 의미있는 시점이란?
- 1차 목표 기능 개발 완료 시점
- 중요 이슈 해결 시점
- 소프트웨어 배포 시점
등등 다양한 시점을 의미있는 시점이라고 할 수 있다.
( v2.3.0 , v2.3.0-rcN , v1.15.3 ... )
Git Tag의 종류
- Lightweight 태그 : 버전명과 같은 태그명만 남기는 태그
$ git tag [태그명]
- Annotated 태그 : Git DB에 이름,이메일,날짜,메세지 등을 저장한 태그
$git tag -a [태그명] -m [태그 메시지]
- 태그 정보 확인하기
$git show [태그명]
특정 시점의 커밋 태그하기
1) 태깅하고자 하는 커밋의 ID 값을 확인한다. ($git log 활용)
2) ID를 활용하여 태그를 생성한다.
$git tag -a [태그명] [커미ID] -m [태그메세지]
$git log --oneline
Tag 활용 전략
Git을 이용한 태그 생성 시점은 조직마다 다를 수 있다.
- 태그 생성 시점, 태그명 규칙, 태그 메시지 규칙 ...
소스코드의 효율적 관리를 위해 생성 시점과 방법에 대한 일관성 있는 규칙(프로세스)를 통해 정책화 해야한다.
- 코드프레소 Java 웹 개발 체험단 활동 중
- 코드프레소 웹개발 트랙의 "실무자가 알려주는 Git 활용한 프로젝트 관리" 내용입니다.
- 코드프레소 URL: https://www.codepresso.kr/
'EXTERNAL ACTIVITY > Code Presso -웹개발 트랙 체험단-' 카테고리의 다른 글
<코드 프레소 웹개발 트랙> Java 프로그래밍 초급 (0) | 2022.01.17 |
---|---|
<코드 프레소 웹 개발 트랙> 실무자가 알려주는 Git 활용한 프로젝트 관리[2] (0) | 2022.01.15 |
<코드 프레소 웹 개발 트랙> 처음 시작하는 자바 프로그래밍[4] (0) | 2022.01.13 |
<코드 프레소 웹 개발 트랙 > Git 입문 (0) | 2022.01.13 |
<코드프레소 웹 개발 트랙> 처음 시작하는 Java 프로그래밍[3] (0) | 2022.01.13 |