본문 바로가기
EXTERNAL ACTIVITY/Code Presso -웹개발 트랙 체험단-

<코드 프레소 웹 개발 트랙> 실무자가 알려주는 Git 활용한 프로젝트 관리

by jaeaemin 2022. 1. 14.

 

Git 브랜치의 이해

 

branch 란 ?

branch의 예시

  • 본래의 소스코드로부터 파생한 독립적인 작업 공간이다.
  • 최신 커밋을 가리키는 일종의 포인터이다.
  • 매우 가볍고, 생성-이동-병합이 매우 쉽다.
  • 브랜치는 나눠서 사용하는 것은 해당 SW 개발팀의 전략이라고 할 수 있다.
  • 브랜치는 목적에 다라 분기가능하고, 전략은 조직에 따라 달라진다.

 

실제 텐서 플로우의 브랜치를 보면 다음과 같다. 총 46개

 

master 브랜치

  • Git은 기본적으로 먼저 master 브랜치를 생성하고 시작하게 된다.

 

 

Git Branch 실습 

> 처음 git brnach 명령어를 입력하면 아무것도 뜨지 않는다. 

> master 브랜치는 첫 커밋이 생성되어야 포인터로 그 커밋을 가리키게 된다.

 

> 새로운 커밋을 반영하여 addm commit 한 뒤 git branch를 입력해보자 

> 새로운 master branch가 생성된 것을 확인 할 수 있다.

> "master branch는 첫 번째 commit이 생성되어야 포인터를 가리킬 수 있다."

 

 

HEAD

  • 현재 브랜치를 가리키는 포인터이다.
  • 마지막 커밋에 대한 스냅샷이라고도 한다.
  • [ HEAD ]   ==>  [ master ]   ==>   [Commit1]

commt 을 추가해보자&amp;amp;nbsp;

위의 실습에 의해서 현재 commit1 의 내용이 commit2로 업데이트 된 것을 알 수 있다.

이 때 깃은 두 번째 커밋에 대해서 branch와 Head의 포인터가 연쇄적으로 이동하게 된다.

깃의 흐름을 보면 아래와 같이 도식화하여 나타낼 수 있다.

> master branch가 commit의 포인터를 갱신할때 마다 새로 할당하게 된다.

 

 

브랜치의 분기

 > 브랜치는 목적에 따라 분기할 수 있다.

 > 이는 기능 개발을 하는데 용이하게 한다.

 > 아래 그림과 같이 master 브랜치에서 login을 구현하는 branch를 생성 할 수 있다.

 

 

 

브랜치 생성 

$git brnach "생성할 브랜치 명"

     위의 명령어를 통해 새로운 branch를 생성할 수 있다.

$git branch 

branch 명령어들을 통해 현재 각 brnach와 Head가 가리키는 branch를 확인 할 수 있다.

$git log 

log에서 확인해보면 HEAD 포인터는 여전히 master를 가리키는 것을 확인할 수 있다.

현재 브랜치의 상황을 보면 다음과 같다. 

새로운 feature-login이라는 브랜치가 생성되었지만, 여전히 HEAD는 master를 가리키고 있다.

 

 

 

브랜치의 이동

 $ git checkout "이동할 브랜치명"

checkout을 통해 master 브랜치에서 새로운 브랜치로 이동한 것을 확인 할 수 있다.

checkout이후 Head는  feature-login의 포인터를 가리키게 된다.

흐름을 살펴보면 아래와 같이 실행될 것이다.

 즉 checkout은 HEAD가 어떤 값의 포인터를 가리키는지 변하게된다

 

 

실습

login branch 에서 작업할 3번째 commit을 생성하자 그 후 커밋을 진행한다&amp;amp;nbsp;

위의 코드를 분석하면 feautre-login branch는 "3번째 커밋"을 완료했고, master branch에는 방금 전과 같이 "2번째 커밋"이 되어있는 상태이다.

깃의 브랜치의 흐름을 보면 다음과 같이 나타낼 수 있다.

즉 master와 feature의 각 브랜치는 다른 커밋을 최신 커밋으로 가리키고 있는 상태가 된다.

- 현재 상황에서 각 브랜치는 독립된 저장물들을 가지고 있다.

- 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가 존재하지 않음)

master 브랜치의 log(history)

 

branch 생성 동시에 checkout 

$ git checkout -b issue
$ git branch
    master
    feature-login
    * issue

 - issue라는 branch를 생성함과 동시에 checkout 하는 명령어 ( -b 옵션 )

 - branch 명령어를 통해 branch 상태를 확인

 - 이 때 HEAD 포인터는 issue라는 branch의 포인터를 가지게 된다.

 - 하지만 issue는 commit을 가지지 않기 때문에 issue는 아무것도 참조하지 않는다.

현재 issue branch만 생성 후 checkout 했기 때문에 다음의 flow를 가진다

 - 여기서 새로운 커밋을 생성하면 각 branch와 커밋은 어떻게 되는지 알아보자

   다음의 코드를 통해 MainService.java 파일이 수정되어서 새로운 변경점이 생기고 add -> commit을 통해서 새로운 버전을 생성한다.

  정리하면 5번째 커밋이 issue branch에서 커밋되었고, 이 는 issue branch에만 적용된다.

  그림으로 도식화하면 아래와 같다.

 

 

 

 

 


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 브랜치의 최신 커밋

그림과 같이&amp;amp;nbsp; 부모- 양 종단간의 커밋 총 3개의 커밋을 merge 할 수 있다.

 

Git의 브랜치 병합은 항상 성공하지 않는다. 

서로 병합하는 브랜치 사이 파일이 동일하지 않는 경우, 어떤 버전으로 수정해야 하는지 알지 못하기 때문이다.

이를 변경사항의 충돌이라고 한다.

 

 

 

 

 

Conflict ( 변경 사항 충돌 )

 

git은 항상 병합(merge)에 성공할까? 

 - 정답은 아니다. 깃의 버전의 흐름 사이 다른 변경점이 있는 경우 충돌이 발생한다.

 - 어떤 변경사항을 반영할지 결정하여서 반영해야 한다.

 - 직접 merge 하는 방법 , Tool을 이용해 merge하는 방법 2가지가 존재한다.

 

해결방법

1) 직접 merge

 직접 충돌 파일을 수정하여서 merge한뒤 커밋하는 방법

 

2) mergetool 사용하기

 $ git mergetool

 <오류 발생 시> $git config merge.tool vimdiff

&lt;master 변경점&gt; &lt;공통부모 변경점&gt; &lt;feature 변경점&gt; &lt;MainService.java 파일&gt; 순

  > 각 변경점, 공통부모들을 확인하면서 아래에 MainService 파일을 수정할 수 있다.

  > 3-Way merge를 사용하므로 총 3개의 상위 창들이 생성된다.

  > 완료된 병합 커밋은 아래와 같은 흐름을 가지게 된다

 

 

 

 

 


Tag

tag

  •  특정 branch위에서 생성되어 특정 시점의 소스코드 정보를 기록히는 것을 의미한다.
  • 프로젝트 진행중 의미있는 시점의 커밋을 태깅한다.
  • 의미있는 시점이란? 

       - 1차 목표 기능 개발 완료 시점

       - 중요 이슈 해결 시점

       - 소프트웨어 배포 시점 

         등등 다양한 시점을 의미있는 시점이라고 할 수 있다.

         ( v2.3.0 , v2.3.0-rcN , v1.15.3 ... )

 

tensorflow의 tags 확인&nbsp;

 

 

 

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/ 

반응형