프로젝트 생산성

[Git] 버전 관리의 꽃, 브랜치(branch)

:) :) 2024. 9. 14. 15:55

[이전 포스트]

 

[Git] Git 내부 구조 알아보기, objects - commit, blob, tree

[ 이전 포스트 ]  [Git] 개발자 필수 도구, Git이 뭔데?Git이란?Git은 소스코드나 파일의 변화를 추적하는 버전 관리 시스템(VCS, Version Control System)입니다.Git의 설계 목표는 다음과 같습니다.빠른 속

300-29-1.tistory.com

 


 

 

 

Git - Branches in a Nutshell

3.1 Git Branching - Branches in a Nutshell Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat

git-scm.com

깃북 3.1 브랜치란 무엇인가에 대한 발췌 및 정리입니다.

 


 

 

브랜치(branch)란?

https://www.nobledesktop.com/learn/git/git-branches

브랜치는 Git에서 독립적인 개발 흐름을 만들 수 있게 해주는 핵심 기능입니다.

 

이미 운영중인 프로그램에 대해,

갑자기 기능 개선을 위해 코드를 수정해야 할 상황이 발생했다고 생각해봐요.

코드를 수정한다는 것은 곧 에러가 발생할 여지를 만들게 되는 것이기 때문에,

운영 중인 서비스에 대한 직접적인 코드 수정은 절.대. 금기사항입니다.

 

따라서 이러한 이슈 발생 시,

새로운 개발 흐름을 만들어(branching)

기존에는 영향이 가지 않게 작업을 진행한 후

테스트가 완료되면 기존 흐름에 다시 병합(merging)하는 방법을 사용합니다.

 

Git 브랜치는 위와 같은 상황 말고도

다양한 상황에서 많은 장점을 가지는데,

믿기 어려울 정도로 가벼워

Git의 핵심 기능으로 꼽히고 있습니다.

 

다른 VCS와 달리, Git은 커밋마다 스냅샷을 저장하는 방식 덕분에

브랜치를 만들 때 드는 오버헤드가 거의 없습니다!

(사실 상 커밋에 대한 포인터 하나를 만드는 겁니다!)

브랜치란 무엇인가 - 더 제대로 알아보기

깃의 브랜칭을 알아보기 전에,

깃이 데이터를 어떻게 저장하는 지 제대로 알아봐야 합니다.

 

 

[Git] Git 내부 구조 알아보기, objects - commit, blob, tree

Git은 Unix File System과 비슷하다Git의 파일시스템은 UNIX 파일시스템과 비슷합니다.Git은 각 파일 내용을 blob으로 표현합니다. UNIX FS가 파일을 디렉토리로 묶어 관리하는 것 처럼Git은 blob을 tree로 묶

300-29-1.tistory.com

 

 

Git은 데이터를 변경 사항(Diff)으로 기록하지 않고,

연속적인 스냅샷 형태로 기록하는 것을 알 수 있습니다.

 

이 구조 아래에서, Git 커밋을 하면

데이터 스냅샷에 대한 포인터(트리의 entry point),

작성자나 커밋 메세지 같은 메타데이터,

이전 커밋(부모 커밋)에 대한 포인터 등을 포함해 커밋 객체를 저장합니다.

 

 

 

브랜치의 이해를 위해 예제를 살펴보겠습니다.

브랜치 이해를 위한 예제

$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'

파일이 3개 있는 디렉토리가 하나 있고,

이 파일을 Staging Area에 저장하고 커밋하는 예제입니다.

 

파일을 Stage 하면 (git add) Git 저장소에 각 파일에 대한 blob이 생깁니다.

따라서 총 3개의 blob이 생깁니다.

 

이후 커밋하면(git commit)

먼저 각 blob을 관리하는 트리 객체를 생성한 후,

메타 데이터와 트리를 가리키는 포인터를 포함해

커밋 객체를 만듭니다.

commit, tree, blob objects map

커밋 객체 98ca9에 대해,

커밋 정보와 더불어

해당 커밋이 가지고 있는 트리 객체와

blob 객체 3개를 나타낸 그림입니다.

 

아래 그림은 파일에 대한 수정 후 커밋 작업을 두 번 반복한 이후의 예시입니다.

루트 커밋 98ca9 에 이어서

34ac2, f30ab 커밋을 진행했음을 확인할 수 있습니다.

Snapshot A, B, C에는 각 커밋과 연결된 트리 및 blob에 대한 포인터가 존재합니다.

 

 

master 브랜치

자, 이 그림에서부터 브랜치를 이해할 수 있습니다.

Git의 브랜치는 커밋 사이를 가볍게 이동할 수 있는 어떤 포인터 같은 것입니다.

기본적으로 Git은 master라는 브랜치를 만듭니다.

 

처음 커밋하면(98ca9)

master 브랜치는 이 98ca9 커밋을 가리킵니다.

이후 커밋을 만들면, master 브랜치는 자동으로 가장 마지막 커밋을 가리킵니다.

 

f30ab가 가장 마지막에 생성된 커밋이라서, master 브랜치는 해당 커밋을 가리키고 있다

 

f30ab가 가장 마지막에 생성된 커밋이라서, master 브랜치는 해당 커밋을 가리키고 있습니다.

 

v1.0 포인터는 f30ab를 가리키는 일종의 태그입니다.

(현재는 무시)

 

HEAD는 현재 사용자가 작업중인 브랜치를 의미하는 포인터입니다.

(아래 링크 및 부록 참고 - HEAD is YOU.)

 

What is HEAD in Git?

You see the Git documentation saying things like The branch must be fully merged in HEAD. But what is Git HEAD exactly?

stackoverflow.com

[De Novo의 답변 참고]

 

 

 

새 브랜치 생성

브랜치를 새로 하나 만들어봅시다.

아래와 같이 git branch 명령으로 testing 브랜치를 만듭니다.

$ git branch testing

하나의 커밋 히스토리를 가리키는 두 브랜치, testing 브랜치를 생성했으나 작업중인 곳은 아직 master

 

 

현재 작업중인 곳은 HEAD 가 가리키는 master → f30ab 커밋의 위치였기 때문에,

이 시점에서 새로 만든 브랜치 역시

f30ab(마지막 커밋)를 가리키고 있습니다.

 

 

작업 브랜치 변경하기

git checkout 명령으로 다른 브랜치로 이동할 수 있다. 한번 testing 브랜치로 바꿔봅시다.

$ git checkout testing

HEAD는 testing 브랜치를 가리킴

 

여기서 커밋을 새로 한 번 해볼까요??

$ vim test.rb
$ git commit -a -m 'made a change'

HEAD가 가리키는 testing 브랜치가 새 커밋을 가리킴

 

testing 브랜치가 새로운 커밋을 참조하게 되었습니다!

그러나 master 브랜치는 여전히 이전 커밋을 가리키고 있습니다.

master에서 작업한 커밋이 아니었기 때문입니다.

 

“브랜치는 특정 커밋에 대한 참조(포인터)입니다.”

 

 

HEAD를 다시 master로 옮겨볼까요? 이후에 커밋을 해봅시다.

$ git checkout master

로컬 깃에서, 작업 및 커밋하는 개체는 그 시점의 나 자신밖에 없기 때문에,

항상 HEAD 포인터를 이리저리 돌려가며 작업하게 됩니다.

 

 

master브랜치에서 파일 수정 후 커밋을 새로 해봅시다.

$ vim test.rb
$ git commit -a -m 'made a change'

갈라진 브랜치

 

프로젝트 히스토리가 분리되었습니다.

 

처음에 testing 브랜치를 하나 만들어 그 브랜치에서 작업하고,

다시 원래 브랜치-master로 되돌아와서 다른 일을 했습니다.

 

두 작업 내용은 서로 독립적으로 각 브랜치에 존재합니다.

간섭이 없습니다.

 

이렇게 커밋 사이를 자유롭게 이동하다가,

때가 되면 두 브랜치를 Merge 합니다.

 

 

 

Appendix

HEAD

우선 git에서 HEAD는 commit object를 참조하는 포인터입니다.

(일반적으로 HEAD는 branch reference를 가리킨다, commit을 가리키는 건 그 예시 중 하나)

디폴트로 모든 로컬 저장소는 master라는 HEAD를 가집니다.

$ cat .git/HEAD

 

추가적으로, HEAD는 커밋, 브랜치 변경, checkout에 따라 가리키는 값이 계속 변화합니다.

“HEAD is YOU” 라는 stackoverflow의 설명을 보면 잘 와닿습니다.

 

What is HEAD in Git?

You see the Git documentation saying things like The branch must be fully merged in HEAD. But what is Git HEAD exactly?

stackoverflow.com

[De Novo의 답변 참고]

 

어쨋든 브랜치 분기를 하지 않은 현재 상태로는

HEAD는 현재 master 브랜치의 가장 최근 커밋을 가리키고 있습니다.

 

git ls-tree HEAD는 HEAD가 가리키는 트리의 object를 확인할 수 있습니다.

 

가장 최근 커밋에 대한 트리 object를 확인하는 것이기에, a.txt 및 b.txt의 blob 내용을 담고 있는 것을 확인할 수 있습니다.

 

HEAD는 현재 커밋을 가리키고 있음을 알 수 있고,

HEAD가 가리키는 commit은 가장 최근의 commit인 “create b.txt”를 의미함을 알 수 있습니다!

 

 

 

git log를 통해 커밋 기록을 확인할 수 있습니다.

맨 아래가 가장 오래된 커밋, 역순으로 저장되어있다.

 

 

 

 

 

[다음 포스트]

 

[Git] 버전 관리의 꽃 2, 병합하기 (Merge)

Git - 브랜치와 Merge 의 기초Merge 시에 발생한 충돌을 다루는 더 어렵고 요상한 내용은 뒤에 고급 Merge 에서 다루기로 한다.git-scm.com'깃북 3.2 브랜치와 Merge 기초'에 대한 발췌 및 정리입니다.     

300-29-1.tistory.com

 

 

 

 

 

Ref.

 

Git - Branches in a Nutshell

3.1 Git Branching - Branches in a Nutshell Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat

git-scm.com

 

 

git branch — Key Puncher

Git 6: Branching

www.keypuncher.net