오픈소스SW

오픈소스SW_Chapter06_브랜치

강용민 2022. 10. 4. 19:31

브랜치

브랜치는 큰 나무 줄기에서 작은 줄기가 뻗어 나오는 것처럼 저장 공간 하나에서 가상의 또 다른 공간을 만드는 것이다.

커밋은 파일의 수정 이력을 관리하는 데 사용한다면, 브랜치는 프로젝트를 독립적으로 관리하는데 사용한다.

잦은 버그 수정과 새로운 기능을 구현할 떄마다 작업 폴더를 복사하는 것은 프로젝트를 유지 관리하는 측면에서 좋지 않기에 개발자는 항상 안정된 코드 상태를 유지하고, 개발 중인 작업과 안정된 코드 상태를 구분하여 관리해야 한다.

 

깃 브랜치 특징

  • 깃 브랜치는 기존 폴더를 복제하는 것과 다르게 가상 폴더를 사용하여 개발 작업을 구분한다.
  • 가상 폴더
    • 깃의 브랜치는 작업 폴더를 실제로 복사하지 않고, 가상 폴더로 생성한다. --> 외부적으로는 물리적인 파일 하나만 있는 것으로 보임
    • 생성된 작업 폴더는 물리적으로 복제된 구조보다 유연하게 처리할 수 있다.
    • 브랜치로 생성된 가상 폴더는 빠르게 공간 이동이 가능하다.
  • 독립적인 동작
    • 브랜치를 이용하면 원본 폴더와 분리하여 독립적으로 개발 작업을 수행할 수 있음
    • 기존에는 소스 코드의 작업 폴더를 별도로 생성함
      • 물리적으로 복사된 각자의 폴더에서 코드를 작업한 후 소스 코드 2개를 다시 하나로 합쳐야 했음
      • 코드를 하나로 합치려면 작업 내역들을 일일이 찾아 정리해야 했기에 소스 코드를 하나로 통합하는 것은 매우 힘든 작업이였다.
    • 깃과 같은 버전 관리 시스템을 이용하면 분리된 코드를 좀 더 쉽게 병합할 수 있다.
      • 분리된 브랜치에서 소스 코드를 각자 수정한 후 원본 코드에 병합하는 명령만 실행하면 된다.
    • 깃의 브랜치는 규모가 큰 코드 수정이나 병합을 처리할 떄 매우 유용하다.
  • 빠른 동작
    • 기존의 다른 버전 관리 도구도 대부분 브랜치 기능을 지원한다.
    • 보통 다른 VCS들은 브랜치를 생성할 떄 내부 파일 전체를 복사한다. 그렇기에 파일 크기가 클수록 브랜치를 생성하는 데 시간이 오래 걸린다.
    • 깃의 브랜치 기능은 다른 버전 관리 도구보다 가볍고, 브랜치 전환이 빠른 것이 특징이다.
    • 깃은 Blob 개념을 도입하여 내부를 구조화했다.
      • Blob은 포인터와 유사한 객체이며 깃은 브랜치를 변경할 때 포인터를 이동하여 빠르게 전환한다.
    • 브랜치 명령을 사용하면 내부적으로 커밋을 하나 생성하여 브랜치로 할당한다.

 

기본 브랜치

모든 커밋과 이력은 브랜치에 기록되며 깃은 최소한 브랜치가 1개 이상 필요하다.

저장소를 처음 초기화하면 master 브랜치 하나가 자동으로 생성된다. 그렇기에 첫 번쨰 커밋은 master 브랜치에서 시작한다.

 

브랜치 생성

브랜치는 가상의 작업 폴더이다.

브랜치는 공통된 커밋을 가리키는 지점이며 브랜치는 커밋처럼 SHA1 해시를 가리킨다.새 브랜치를 생성하면 포인터만 있는 브랜치가 생성된다.

새롭게 브랜치가 생성되면 독립된 공간을 할당하며 이 공간은 기존 작업 영역에는 영향을 않는 새로운 가상 공간이 생긴다.

git branch 브랜치이름 커밋ID

일반적으로 브랜치 생성 명령을 실행하면 현재 커밋을 가리키는 HEAD를 기준으로 생성되지만 직접 커밋 ID 인자 값을 지정하면, 지정한 커밋 ID를 기준으로 브랜치를 생성된다.

 

브랜치 확인

git branch

현재 모든 브랜치가 나열된다.

  • -v , -verbose : 브랜치 이름, 커밋 ID, 커밋 메시지를 같이 볼 수 있다.
  • -r : 원격 저장소의 리모트 브랜치 목록을 확인할 수 있다.
  • -a : 모든 브랜치의 정보를 확인할 수 있다.
  • -vv : 트래킹 브랜치
  • -u : 업스트림 직접 설정
  • -d : 삭제
  • -D : 강제삭제
git rev-parse 브랜치이름

브랜치는 특정한 커밋의 해시 값(SHA1)을 가리키는데 rev-parse를 시용하면 현재 브랜치가 어떤 커밋 해시 값(SHA1)을 가리키는지 확인할 수 있다.

 

브랜치 이동

git checkout 브랜치명

현재 브랜치를 떠나 새로운 브랜치로 들어가는 명령어이다.

주의할 점은 깃은 하나의 워킹 디렉터리만 가지고 있다는 것이다. 워킹 디렉터리는 선택한 브랜치 하나만 연결되어 있다.

즉, 한 브랜치에서만 작업과 커밋을 할 수 있으므로 다른 브랜치에서 작업하려면 반드시 브랜치를 변경하여 워킹 디렉터리를 재설정해야 한다.

  • - : 이전 브랜치로 이동가능
  • -b 브랜치 생성과 이동을 한 번에 할 수 있다.

 

브랜치 동작 원리

checkout 명령어로 브랜치가 변경되면 깃은 내부적으로 몇 가지 동작을 수행한다.

  • HEAD가 브랜치의 마지막 커밋을 의미하기 때문에 브랜치가 이동하면 HEAD 포인터도 함께 이동한다.
  • 변경된 브랜치로 새로운 작업을 할 수 있도록 워킹 디렉터리를 변경한다.
    • 기존 브랜치의 워킹 디렉터리를 정리해야 한다. 그렇지 않으면 브랜치를 변경할 수 없다.

 

워킹 디렉터리 정리

checkout을 사용하여 브랜치를 이동할 때는 주의 사항이 있다.

현재 작업하고 있는 워킹 디렉터리를 정리하고 넘어가야 한다. 브랜치 동작 원리에서 브랜치가 변경되면 워킹 디렉터리도 같이 변환된다.

따라서 워킹 디렉터리 안에서 작성하던 내용이 있고, 커밋을 하지 않았다면 체크아웃할 때 경고가 발생한다.

 

HEAD 포인터

깃은 마지막 커밋 정보를 기반으로 새로운 커밋을 생성한다.

시스템이 매번 커밋할 때마다 마지막 커밋 정보를 찾으면 부하가 발생하기에 깃은 마지막 커밋을 쉽게 확인할 수 있도록 특수한 포인터를 제공한다.

HEAD는 작업 중인 브랜치의 마지막 커밋 ID를 가리키는 참조 포인터이기에 다양한 명령어를 입력할 떄도 기준으로 사용한다.

  • 브랜치를 이동하면 HEAD 포인트도 이동된다.
  • 브랜치가 여러 개면 HEAD 포인트도 여러 개이다.
  • 브랜치마다 마지막 커밋 ID를 가리키는 HEAD 포인터가 하나씩 있다.
  • 상대적 위치
    • '^'와 '~'을 이용하여 HEAD 기준으로 몇 번째인지 상대적인 위치를 지정한다.
    • HEAD^^^, HEAD~3등

 

AHEAD / BHEAD

원격 저장소와 연동하여 깃을 관리한다면 브랜치마다 HEAD가 2개있다.

로컬 저장소 브랜치 HEAD 포인터와 원격 저장소 브랜치의 HEAD 포인터인데, 두 저장소는 물리적으로 서로 다른 저장소이므로 마지막 커밋 위치가 일치하지 않을 수 있다.

그렇기에 깃은 AHEAD와 BHEAD를 따로 나누어 원격 저장소의 HEAD와 로컬 저장소의 HEAD와 비교한다.

 

AHEAD

서버로 전송되지 않은 로컬 커밋이 있는 것

BHEAD

로컬저장소로 내려받지 않는 커밋이 있는 것

 

커밋 이동

브랜치는 특정한 커밋에 별명을 부여한 것과 같다. 그러기에 브랜치로 이동할 때 꼭 브랜치 이름만 사용할 필요는 없다. 브랜치 이름 대신 커밋 해시키를 사용하여 체크아웃할 수 도 있다.

git checkout 커밋해시키

 

원격 브랜치

깃은 DVCS로 로컬 저장소도 하나의 저장소고, 원격 저장소도 하나의 저장소이다.

리모트 브랜치는 원격 저장소에 생성한 브랜치를 지칭한다. 로컬 저장소에 생성한 브랜치는 서버로 공유할 수 있다. 다만 원격 저장소와 연결된 로컬 저장소에서 새로운 브랜치를 생성한다고 해서 자동으로 원격 저장소에도 브랜치가 생성되는 것은 아니다. 또한 원격 저장소와 로컬 저장소의 브랜치 이름은 보통 같지만, 반드시 일치하지 않아도 괜찮다.

 

브랜치 추적

깃의 브랜치는 특정 커밋 해시 값을 가리키는 포인터이다. 이는 원격 저장소의 브랜치도 마찬가지다.

깃에서 브랜치 추적은 원격 저장소의 브랜치를 가리키는 의미로 트래킹 브랜치라고 한다. 추적 브랜치는 원격 브랜치의 마지막 커밋 해시 값을 가리키며, 이 포인터의 정보는 .git/refs 폴더 안에 저장되어 있다.

다른 표현으로는 업스트림(Upstream) 트래킹이라 하며 로컬 저장소의 브랜치와 원격 저장소의 브랜치는 업로드할 수 있도록 매칭되어 있는데 이를 업스트림트래킹이라 한다. 

 

브랜치 업로드

로컬 저장소의 브랜치를 원격 저장소에 동기화하려면 푸시 작업을 해야한다.

위에 설명되어 있다시피 원격 저장소와 로컬 저장소의 브랜치 이름이 다를 수 있다. 그럴 경우에는 다음과 같이 해야한다.

git push 원격저장소별칭 브랜치이름:새로운브랜치

 

업스트림 트래킹

다른 브랜치를 풀 작업으로 받아 트래킹 브랜치를 활성화하거나 직접 트래킹 브랜치를 지정할 수 있다.

git checkout --track 원격브랜치이름/로컬브랜치이름

 

원격 브랜치 복사

원격 저장소와 로컬 저장소의 브랜치 목록은 서로 다를 수 있다.

이렇게 생성된 원격 저장소의 리모트 브랜치를 이용해서 로컬 저장소에도 새로운 브랜치를 생성하여 동기화할 수 있다.

git checkout -b 새이름 원격저장소별칭/브랜치이름

 

리모트 브랜치 삭제

git push 리모트저장소별칭 --delete 리모트브랜치이름

 

문제

커밋과 브랜치의 차이점은 무엇인가

커밋은 파일의 수정 이력을 관리하는 데 사용한다면, 브랜치는 프로젝트를 독립적으로 관리하는데 사용한다.

 

깃 브랜치의 특징은 무엇이 있는가

  • 작업 폴더를 실제로 복사하지 않고 가상 폴더로 생성한다.
  • 원본 폴더와 분리하여 독립적으로 개발 작업을 수행할 수 있다.
  • Blob 개념을 도입하여 내부를 구조화했으며 이를 통해 빠른 동작을 할 수 있다.

브랜치 생성하려명 어떤 명령어를 실행해야 하는가

git branch 브랜치이름 커밋ID

 

브랜치생성과 이동을 동시에 하려면 어떤 명령어를 실행해야 하는가

git checkout -b 브랜치명

 

HEAD포인터는 무엇인가?

깃은 마지막 커밋 정보를 기반으로 새로운 커밋을 생성하는 데 HEAD는 작업 중인 브랜치의 마지막 커밋ID를 가리키는 참조 포인터이다.

 

브랜치를 옮길 때 주의할 점은 무엇인가?

checkout 명령어를 실행할 때 HEAD 포인터가 옮겨지고, 워킹디렉토리도 변경된다. 그렇기에 기존의 워킹디렉토리를 commit등으로 정리를 해야 한다.

 

원격저장소와 연동하면 브랜치마다 HEAD가 AHEAD / BHEAD가 나뉘어있다. 각 HEAD는 어떤것을 의미하는?

AHEAD는 서버로 전송되지 않은 로컬 커밋이 있는 것이고, BHEAD는 로컬 저장소로 내려받지 않은 커밋이 있다는 것을 의미한다.

 

 

 

'오픈소스SW' 카테고리의 다른 글

오픈소스SW_Chapter02_깃설정  (0) 2022.10.10
오픈소스SW_Chapter01_깃과 버전 관리  (0) 2022.10.10
git과 github의 차이  (0) 2021.08.04
Git_2.브랜치  (0) 2021.08.04
오픈소스SW_Chapter0_개요  (0) 2021.08.04