본문 바로가기
✍ 따뜻한 개발 공부

[깃허브] 깃허브 제대로 이해하기(주말공부) / 깃허브 튜토리얼 backlog에서 학습

by 따따시 2022. 11. 5.
이 포스팅 내용은 직접 작성한 내용이 아니고,
https://backlog.com/git-tutorial/kr/
위 싸이트의 내용을 보면서 스스로 공부하며 복습한 내용입니다.
(내용은 모두 위 싸이트에서 참고한 내용이에요)

 

Git 

Git의 '커밋' 작업은 '작업 트리'에 있는 변경 내용을 저장소에 바로 기록하는 것이 아니라 그 사이 공간인 '인덱스'에 파일 상태를 기록한다.(stage - 인덱스에 올리는 작업을 스테이징한다고도 함)

따라서 저장소에 변경 사항을 기록하기 위해서는, 기록하고자 하는 모든 변경 사항들이 '인덱스'에 존재해야 한다.

예를 들어, 10개의 파일을 수정했지만 그 중에 7개만 저장소에 공개하고 싶을 때, 변경한 10개의 파일 중 7개를 선택하는 작업이 바로 '인덱스에 등록' 또는 '스테이징(stage)'이라 표현하는 작업이다.

이렇게 인덱스란 공간(=가상 공간)이 중간에 있는 덕분에 작업 트리 안에 있는 커밋이 필요 없는 파일들을 커밋에 포함하지 않을 수 있고, 파일에서 내가 원하는 일부 변경 사항만 인덱스에 등록해 커밋할 수 있는 것

 

>> 아!!!! 그래서 스테이징을 하는 구나!!!!!!! (유레카)

 

브랜치란?

소프트웨어를 개발할 때에 개발자들은 동일한 소스코드를 함께 공유하고 다루는데 동일한 소스코드 위에서 어떤 개발자는 버그를 수정하기도 하고 또 다른 개발자는 새로운 기능을 만들어 내기도 한다. 이와 같이 여러 사람이 동일한 소스코드를 기반으로 서로 다른 작업을 할 때에는 각각 서로 다른 버전의 코드가 만들어 질 수 밖에 없다.

이럴 때, 여러 개발자들이 동시에 다양한 작업을 할 수 있게 만들어 주는 기능이 바로 '브랜치(Branch)' 다.

각자 독립적인 작업 영역(저장소) 안에서 마음대로 소스코드를 변경할 수 있다. 이렇게 분리된 작업 영역에서 변경된 내용은 나중에 원래의 버전과 비교해서 하나의 새로운 버전으로 만들어 낼 수 있다.

 

브랜치(branch)란?

브랜치란 독립적으로 어떤 작업을 진행하기 위한 개념

필요에 의해 만들어지는 각각의 브랜치는 다른 브랜치의 영향을 받지 않기 때문에, 여러 작업을 동시에 진행할 수 있다.

 

또한 이렇게 만들어진 브랜치는 다른 브랜치와 병합(Merge)함으로써, 작업한 내용을 다시 새로운 하나의 브랜치로 모을 수 있다.

 

여러 명이서 동시에 작업을 할 때에 다른 사람의 작업에 영향을 주거나 받지 않도록, 먼저 메인 브랜치에서 자신의 작업 전용 브랜치를 만든다. 그리고 각자 작업을 진행한 후, 작업이 끝난 사람은 메인 브랜치에 자신의 브랜치의 변경 사항을 적용한다.

이렇게 함으로써 다른 사람의 작업에 영향을 받지 않고 독립적으로 특정 작업을 수행하고 그 결과를 하나로 모아 나가게 된다.

이러한 방식으로 작업할 경우 '작업 단위', 즉 브랜치로 그 작업의 기록을 중간 중간에 남기게 되므로 문제가 발생했을 경우 원인이 되는 작업을 찾아내거나 그에 따른 대책을 세우기 쉬워진다.

 

master 브랜치

저장소를 처음 만들면, Git은 바로 'master'라는 이름의 브랜치를 만들어 둔다.

이 새로운 저장소에 새로운 파일을 추가 한다거나 추가한 파일의 내용을 변경하여 그 내용을 저장(커밋, Commit)하는 것은

모두 'master' 라는 이름의 브랜치를 통해 처리할 수 있는 일이다.

'master'가 아닌 또 다른 새로운 브랜치를 만들어서 '이제부터 이 브랜치를 사용할거야!'라고 선언(체크아웃, checkout)하지 않는 이상, 이 때의 모든 작업은 'master' 브랜치에서 이루어진다.

 

브랜치 만들기

Git 에서는 작업에 따라 자유롭게 브랜치를 만들 수 있다.

그러나 이것을 효과적으로 관리하려면, 먼저 함께 작업할 팀원들과 어떠한 방식으로 브랜치를 만들고 통합할 것인지 미리 정해두는 것이 좋다. 예를 들어 새로운 브랜치를 만들 때에 브랜치 이름은 어떤 규칙으로 지을 것인지 또는 어떤 상황에서 브랜치를 만들 지, 어느 시점에 통합할 것인지 등등 규칙은 정하기 나름!

 

통합 브랜치(Integration Branch)

통합 브랜치란 언제든지 배포할 수 있는 버전을 만들 수 있어야 하는 브랜치

그렇기 때문에 늘 안정적인 상태를 유지하는 것이 중요하다.

* '안정적인 상태'란 현재 작업 중인 소스코드가 모바일에서 동작하는 어플리케이션을 개발하기 위한 것이라면, '그 어플리케이션의 모든 기능이 정상적으로 동작하는 상태'를 의미한다.

 

만약 이 어플리케이션에 어떤 문제가 발견되어 그 문제(버그)를 수정한다던지 새로운 기능을 추가해야 한다던지 해야할 때,

바로 '토픽 브랜치(Topic branch)'를 만들 수 있다. 처음에는 보통 통합 브랜치에서 토픽 브랜치를 만들어 낸다.

일반적으로 저장소를 처음 만들었을 때에 생기는 'master' 브랜치를 통합 브랜치로 사용한다.

 

토픽 브랜치(Topic Branch)

토픽 브랜치란, 기능 추가나 버그 수정과 같은 단위 작업을 위한 브랜치

여러 개의 작업을 동시에 진행할 때에는, 그 수만큼 토픽 브랜치를 생성할 수 있다.

토픽 브랜치는 보통 통합 브랜치로부터 만들어 내며,

토픽 브랜치에서 특정 작업이 완료되면 다시 통합 브랜치에 병합하는 방식으로 진행된다.

이러한 토픽 브랜치는 '피처 브랜치(Feature branch)' 라고 부르기도 한다.

 

브랜치 전환하기

Git에서는 항상 작업할 브랜치를 미리 선택해야 한다. 처음에 Git을 설치하게 되면 'master' 브랜치가 선택되어 있다.

현재 선택된 브랜치가 아닌 다른 브랜치에서 작업하고 싶을 때에는,  '체크아웃(checkout)' 명령어를 실행하여 원하는 브랜치로 전환할 수 있다. 체크아웃을 실행하면, 우선 브랜치 안에 있는 마지막 커밋 내용이 작업 트리에 펼쳐진다.

브랜치가 전환 되었으므로 이 후에 실행한 커밋은 전환한 브랜치에 추가된다.

 

HEAD

'HEAD' 란 현재 사용 중인 브랜치의 선두 부분을 나타내는 이름

기본적으로는 'master'의 선두 부분을 나타낸다. 'HEAD' 를 이동하면, 사용하는 브랜치가 변경된다.

 

 

커밋을 지정할 때, '~(틸드, 물결기호)'와 '^(캐럿, 삽입기호)'을 사용하여 현재 커밋으로부터 특정 커밋의 위치를 가리킬 수 있다.

때 자주 사용하는 것이 'HEAD' 로서, '~(틸드)'와 숫자를 'HEAD' 뒤에 붙여 몇 세대 앞의 커밋을 가리킬 수 있다.

'^(캐럿)'은, 브랜치 병합에서 원본이 여럿 있는 경우 몇 번째 원본인지를 지정할 수 있다.

 

stash

커밋하지 않은 변경 내용이나 새롭게 추가한 파일이 인덱스와 작업 트리에 남아 있는 채로 다른 브랜치로 전환(checkout)하면,

그 변경 내용은 기존 브랜치가 아닌 전환된 브랜치에서 커밋할 수 있다.

 

단, 커밋 가능한 변경 내용 중에 전환된 브랜치에서도 한 차례 변경이 되어 있는 경우에는 체크아웃에 실패할 수 있다.

이 경우 이전 브랜치에서 커밋하지 않은 변경 내용을 커밋하거나, stash 를 이용해 일시적으로 변경 내용을 다른 곳에 저장하여 충돌을 피하게 한 뒤 체크아웃을 해야 한다.

 

stash 란, 파일의 변경 내용을 일시적으로 기록해두는 영역이다.

stash 를 사용하여 작업 트리와 인덱스 내에서 아직 커밋하지 않은 변경을 일시적으로 저장해 둘 수 있다.

이 stash 에 저장된 변경 내용은 나중에 다시 불러와 원래의 브랜치나 다른 브랜치에 커밋할 수 있다.

 

 

브랜치 통합하기

작업이 완료된 토픽 브랜치는 최종적으로 통합 브랜치에 병합된다.

브랜치 통합에는 'merge' 를 사용하는 방법과 'rebase'를 사용하는 방법의 2가지 종류가 있다.

어느 쪽을 사용하느냐에 따라 통합 후의 브랜치의 이력이 크게 달라진다고 한다. 

1. merge : 빨리감기병합(=패스트포워드)

2. rebase : 하나의 줄기처럼 뒤에 연결되는 방식

merge

merge 를 사용하면, 여러 개의 브랜치를 하나로 모을 수 있다.

이 'bugfix' 브랜치를 'master' 브랜치로 병합할 때,

'master' 브랜치의 상태가 이전부터 변경되어 있지만 않으면 매우 쉽게 병합할 수  있다.

'bugfix' 브랜치의 이력은 'master' 브랜치의 이력을 모두 포함하고 있기 때문에, 'master' 브랜치는 단순히 이동하기만 해도 'bugfix' 브랜치의 내용을 적용할 수 있다. 또한 이 같은 병합은 'fast-forward(빨리 감기) 병합'이라고 부른다.

-> 그냥 단순히 master를 bugfix 브랜치로 이동한다는 의미네

 

 

하지만 'bugfix' 브랜치를 분기한 이후에 'master' 브랜치에 여러 가지 변경 사항이 적용되는 경우도 있다.

이 경우에는 'master' 브랜치 내의 변경 내용과 'bugfix' 브랜치 내의 변경 내용을 하나로 통합할 필요가 있다.

 

따라서 양쪽의 변경을 가져온 'merge commit(병합 커밋)'을 실행하게 된다.

병합 완료 후, 통합 브랜치인 'master' 브랜치로 통합된 이력이 아래 그림과 같이 생기게 된다.

 

병합 실행 시에 'fast-forward 병합'이 가능한 경우라도 'non fast-forward 병합' 옵션을 지정하여 아래 그림과 같이 만들어 낼 수도 있다.

'non fast-forward 병합'을 실행하면, 브랜치가 그대로 남기 때문에 그 브랜치로 실행한 작업 확인 및 브랜치 관리 면에서 더 유용할 수 있다.

 

 

rebase

위와 마찬가지로, 'master' 브랜치에서 분기하는 'bugfix' 브랜치가 있다고 가정한다.

 

 

 

'non fast-forward 병합' 방식으로 진행되는 시나리오

우선 'bugfix' 브랜치를 'master' 브랜치에 rebase 하면, 'bugfix' 브랜치의 이력이 'master' 브랜치 뒤로 이동된다.

그 때문에 그림과 같이 이력이 하나의 줄기로 이어지게 됩니다.

 

이 때 이동하는 커밋 X와 Y 내에 포함되는 내용이 'master'의 커밋된 버전들과 충돌하는 부분이 생길 수 있다.

그 때는 각각의 커밋에서 발생한 충돌 내용을 수정할 필요가 있다.

 

'rebase'만 하면 아래 그림에서와 같이, 'master'의 위치는 그대로 유지된다.

'master' 브랜치의 위치를 변경하기 위해서는 'master' 브랜치에서 'bugfix' 브랜치를 fast-foward(빨리감기) 병합 하면 된다.

 

 

 

merge 와 rebase 는 통합 브랜치에 토픽 브랜치를 통합하고자 하는 목적은 같으나, 그 특징은 약간 다르다.

  • merge
    변경 내용의 이력이 모두 그대로 남아 있기 때문에 이력이 복잡해짐.
  • rebase
    이력은 단순해지지만, 원래의 커밋 이력이 변경됨. 정확한 이력을 남겨야 할 필요가 있을 경우에는 사용하면 안됨.

merge 와 rebase 는 팀 운용 방침에 따라 구별해 쓸 수 있다.
예를 들어 이력을 하나로 모두 모아서 처리하도록 운용한다고 치면 아래와 같이 구별해 사용할 수 있다.

  • 토픽 브랜치에 통합 브랜치의 최신 코드를 적용할 경우에는 rebase 를 사용,
  • 통합 브랜치에 토픽 브랜치를 불러올 경우에는 우선 rebase 를 한 후 merge

 

댓글