본 게시글은 모두의 git,github(저자 : 강민철)의 내용을 개인적으로 정리하는 글입니다.
브랜치란?
브랜치는 마치 줄기에서 뻗어 나오는 나뭇가지와 같이 버전을 여러 흐름으로 나누어 관리하는 방법이다.
브랜치는 버전의 분기이다.
작업을 분기하고 싶을 때 브랜치를 나누면 된다.
버전을 나누어 관리하는 것은 아래의 3단계로 버전을 관리하는 것을 의미한다.
- 브랜치를 나눈다.
- 각자 브랜치에서 작업한다.
- (필요할 경우) 나눈 브랜치를 합친다.
브랜치 나누고, 합치기
깃이 제공하는 가장 기본적인, 최초의 브랜치를 master 브랜치라고 한다.
가령 로컬 저장소를 만들고, 커밋 세 개를 만들었다고 가정하자
이 커밋 모두는 master 브랜치에 속한다.
master 브랜치에 만들어진 세 커밋을 master 1번 커밋, master 2번 커밋, master 3번 커밋이라고 한다면
마스터 브랜치는 아래와 같다.
master의 최신 커밋에서 foo라는 브랜치를 만들고, foo 브랜치에 커밋을 두 개 추가하면 아래의 왼쪽과 같다.
이후 master의 최신 커밋에서 새로운 커밋을 추가하면 아래의 오른쪽과 같다.
여기서 주목해야 할 점은 master 브랜치 입장에서는 커밋이 세 개 밖에 없다는 점이다.
반면, foo 브랜치 입장에서는 커밋이 5개이다.
foo는 master 브랜치의 세 번째 커밋에서 뻗어 나온 브랜치이기 때문에 master 브랜치의 커밋 세 개를 모두 포함하고 있기 때문이다.
여기서 master의 4번 커밋에서 bar라는 브랜치를 나누고, bar에 두 개의 커밋을 추가하면 아래의 그림과 같다.
HEAD와 체크 아웃
HEAD는 현재 작업 중인 브랜치의 최신 커밋을 가리키는 일종의 표시이다.
보통은 현재 작업 중인 브랜치의 최신 커밋을 가리키지만, 브랜치를 나누고 합치는 과정에서 HEAD의 위치를 자유자재로 바꿀 수 있다.
체크아웃은 특정 브랜치에서 작업할 수 있도록 작업 환경을 바꾸는 것을 의미한다.
특정 브랜치로 체크아웃하게 되면 HEAD의 위치가 해당 브랜치의 최신 커밋을 가리키고, 작업 디렉터리는 체크아웃한 브랜치의 모습으로 바뀌게 된다.
브랜치 나누고, 합치기 소스트리 실습
브랜치 나누기
위 그림과 같이 브랜치를 나눠보자
현재 master 브랜치 3번째 커밋 상태이다.
여기서 상단의 브랜치 버튼을 누른다.
브랜치 이름을 입력하고, 새 브랜치 체크아웃을 체크한다.
foo 브랜치로 체크아웃한다는 뜻은 작업 환경을 foo 브랜치로 바꾼다는 의미이다.
마지막으로 브랜치생성 버튼을 누른다.
아래처럼 foo가 진하게 표시되어 있다면 현재 작업 환경이 foo 브랜치임을 나타낸다.
이후 foo 브랜치에서 커밋 두 개를 추가한다.
현재 상황은 아래와 같다.
위에서 언급했듯이 이 상황에서 foo 브랜치가 아니라 master 브랜치로 체크아웃하면 HEAD는 master 3번 커밋을 가리키게 되고, 작업 디렉터리의 파일들도 master 3번 커밋으로 되돌아가게 된다.
master의 최신 커밋인 4번 커밋에서 bar 브랜치를 추가하고, 커밋 세 개를 추가하자.
여기까지 완료했다면 현재 상황은 아래와 같다.
브랜치 병합
브랜치를 하나로 통합하는 것을 병합, 영어로 merge라고 한다.
빨리 감기 병합(fast-forward merge)
위에서 작업했던 브랜치를 예로 들면, master 브랜치와 foo 브랜치를 병합하면 아래와 같은 모양이 된다.
master 브랜치 입장에서는 자신의 브랜치가 마치 빨리 감기 하듯이 foo 브랜치와 동일하게 업데이트되었다.
이처럼 master 브랜치가 빨리 감기 하듯 foo와 동일해질 수 있었던 이유는, foo 브랜치가 master 브랜치에서부터 뻗어 나온 시점부터 병합되는 순간까지 master 브랜치에 어떤 변화도 없었기 때문이다.
그렇기 때문에 foo 브랜치를 master 브랜치로 병합할 때 master 브랜치는 그저 foo 브랜치에 새롭게 쌓인 커밋을 반영만 하면 된다.
이처럼 변화가 없었던 브랜치가 마치 빨리 감기 하듯 업데이트되는 병합 기법을 빨리 감기 병합(fast-forward merge)라고 한다.
빨리 감기 병합 소스트리 실습
먼저 master 브랜치로 체크아웃한다.
이후 foo 브랜치 위에 마우스를 두고 마우스 오른쪽 버튼을 클릭한다.
여기서 현재 브랜치로 foo 병합 버튼을 누르면 병합이 된다.
확인을 눌러준다.
이제 master 브랜치는 foo 브랜치와 같아졌다.
브랜치를 병합하고 나서 더 이상 브랜치에 남은 작업이 없다면 해당 브랜치를 삭제하는 것이 좋다.
foo 브랜치를 삭제해 보자.
브랜치를 삭제하려면 삭제하려는 브랜치가 아닌 다른 브랜치에 체크아웃되어 있어야 한다.
foo 브랜치 위에 마우스를 두고 마우스 우클릭을 한다.
확인 버튼을 누른다.
foo 브랜치가 삭제된 결과는 아래와 같다.
빨리 감기 병합이 아닌 병합
빨리 감기 병합이 아닌 병합은 bar 브랜치에는 없는 커밋이 master 브랜치에 있고, master 브랜치에는 없는 커밋이 bar 브랜치에 있는 상태에서 두 브랜치를 병합하는 것을 뜻한다.
즉, bar 브랜치가 master 브랜치에서부터 뻗어 나온 시점부터 병합되는 순간까지 master 브랜치에 어떤 변화가 있을 때 병합하는 것을 뜻한다.
이런 상황에서는 새로운 커밋이 생성된다.
master 브랜치와 bar 브랜치의 4번 커밋과 병합하면 아래와 같다.
이후 master 브랜치와 bar 브랜치의 6번 커밋과 병합하면 아래와 같다.
빨리 감기 병합이 아닌 병합 소스트리 실습
master 브랜치와 bar 브랜치의 4번 커밋과 병합해 보자.
상단의 병합에서도 브랜치를 병합할 수 있다.
master 브랜치에 병합할 브랜치의 커밋을 클릭한 뒤 확인을 누르면 해당 커밋이 병합된다.
위 그림처럼 bar 브랜치의 4번 커밋을 master 브랜치로 병합하려면 4번 커밋을 클릭한 뒤 확인을 클릭하면 된다.
결과는 아래와 같다.
이번에는 master 브랜치와 bar 브랜치의 6번 브랜치와 병합해 보자
상단의 병합 버튼을 누른 후, bar 브랜치의 6번 커밋을 선택하고 확인을 누른다.
결과는 아래와 같다.
충돌과 해결
충돌
충돌이란 병합하려는 두 브랜치가 서로 같은 내용을 다르게 수정한 상황을 의미한다.
충돌은 여럿이 협업하여 개발할 때 빈번히 발생하므로 언제 발생하고, 어떻게 해결할 수 있는지 꼭 알아야 한다.
예를 들어, master 브랜치에서 foo 브랜치가 뻗어 나왔다고 하자.
master 브랜치는 a.txt 파일의 첫 번째 줄을 B로 수정한 다음 커밋했고, foo 브랜치는 a.txt 파일의 첫 번째 줄을 C로 수정한 다음 커밋했다.
이런 상황에서 foo 브랜치를 master 브랜치에 병합한다면 a.txt 에서 충돌이 발생했다고 한다.
충돌이 발생하면 최종적으로 어떤 브랜치의 내용을 반영할지 우리가 직접 선택해야 한다.
위 상황을 소스트리로 나타내면 아래와 같다.
이제 병합하면 아래와 같이 오류가 뜬다.
a.txt에 변화가 생겼다.
충돌이 발생하면 커밋하지 않은 변경사항이 생기고, 스테이지에 올라가지 않은 파일과 스테이지에 올라간 파일 항목에는 충돌이 발생한 파일이 추가된다.
a.txt를 열어보면 아래와 같다.
해결
충돌이 발생한 파일들의 충돌을 해결한 뒤 다시 커밋해야 브랜치가 올바르게 병합된다.
충돌이 발생한 이유는 병합하려는 두 브랜치가 같은 내용을 서로 다르게 수정했기 때문이다.
따라서 충돌이 발생하면 충돌이 발생한 두 브랜치 중 어떤 브랜치의 내용을 병합 결과에 반영할지 선택하면 된다.
같은 내용을 다르게 수정한 브랜치 중 어떤 브랜치 내용을 최종적으로 반영할지를 직접 선택하는 것을 '충돌을 해결한다'라고 한다.
a.txt의 내용은 아래와 같다.
충돌이 발생한 파일에는 <<<<<<<<<<<<<<, >>>>>>>>>>>, ========== 기호가 표기된다.
이 기호는 일종의 영역 표기이다.
=======를 기준으로 윗부분은 HEAD가 가리키는 브랜치, 즉 현재 체크아웃한 브랜치의 내용이 적혀있고
아랫부분은 병합하려는 브랜치, 즉 foo 브랜치의 내용이 적혀있다.
이 두 영역 중 반영할 부분을 직접 선택해 충돌을 해결해야 한다.
나는 master 브랜치의 내용을 반영하겠다.
스테이지에 올라가지 않은 파일 항목에 있는 a.txt 파일에서 충돌 해결을 클릭하면 '내 것'을 이용해 해결 항목과 '저장소'것을 사용하여 해결 항목이 있다.
'내것'은 현재 체크 아웃된 브랜치의 내용을 병합에 반영하겠다는 의미이다
'저장소'는 병합하려는 브랜치의 내용을 병합에 반영하겠다는 의미이다.
나는 master 브랜치의 내용을 반영할 것이고, 현재 master에 체크아웃되어있기 때문에 '내 것'을 선택하겠다.
확인 버튼을 누른다.
이제 소스트리에는 아래와 같이 표기된다.
이제 충돌이 해결되었으니 커밋을 해주어야 한다.
커밋까지 완료하면 아래와 같이 된다.
브랜치 재배치하기
브랜치 재배치는 브랜치가 뻗어 나온 기준점을 변경하는 것을 말하고, rebase라고 한다.
아래의 상황은 위 그림의 왼쪽과 같다.
우리는 위 그림의 오른쪽이 되는 것이 목표이다.
브랜치를 rebase 하려면 재배치하려는 브랜치로 체크아웃해야 한다.
따라서 foo 브랜치로 체크아웃한다.
이후 master 브랜치의 4번 커밋으로 브랜치를 재배치할 예정이므로 master의 네 번째 커밋에서 마우스 오른쪽 버튼을 클릭 후 재배치를 클릭한다.
확인을 누른다.
foo 브랜치가 master 브랜치의 네 번째 커밋으로 rebase 되었다.
물론 rebase 과정에서 충돌이 충분히 일어날 수 있다.
'Git & GitHub' 카테고리의 다른 글
[Git] Git 명령어 정리 (1) | 2023.12.29 |
---|---|
[GitHub] 소스트리로 clone, push, fetch, pull, pull request 하기 (1) | 2023.12.28 |
[Git] 버전 비교, 커밋 되돌리기, 임시 저장 (+소스트리 실습) (1) | 2023.12.26 |
[Git] 소스트리로 태그 만들기(+커밋 해시 개념) (1) | 2023.12.26 |
[Git] 소스트리(Sourcetree)로 커밋(commit)하기 (0) | 2023.12.25 |