Critical!
- Branching... what is it? why use it?
- Understanding Git HEAD
- Git Branch
- Git Switch
- Git Checkout
Important
- Deleting & Renaming Branches
- Master vs Main Branch
Nice to Have
- HEAD & Refs behind the scenes
브랜치 소개에 앞서, 간단하게 깃이 어떻게 동작하는지 설명한다.
하지만, 실제로 프로젝트에서 작업할 때는, 여러 상황에서 동시에 작업하는 경우가 많다.
한 브랜치에서, 다음 브랜치로 넘어가는 것이 아니라, 여러 가지를 여러 명이 동시에 개발하거나, 동시에 버그를 잡는 작업을 할 수 있다.
이러한 경우에, 한 작업에서 다른 작업으로 넘어가는 직선적인 작업은 불가능하다.
따라서, 서로의 작업이 영향을 미치지 않는 것이라면, 독립적으로 하는 것이 보다 효율적이다.
브랜치는 프로젝트의 타임라인이라 할 수 있다.
우리가 원할 때 별도의 contexts를 생성할 수 있게 한다.
또한, 우리가 한 브랜치에서 어떤 작업을 하든 다른 브랜치에 영향을 미치지 않는다!
마지막엔, 브랜치 결합을 결정하고 병합 명령을 호출해야 하는데 그 방법은 추후에 다룬다.
브랜치를 생성하여 이렇게 독립적으로 작업 하다가
브랜치를 합칠 수 있다.
이전시간에도, 커밋을 할 때 마다 브랜치를 보았다.
마스터 브랜치는 새 브랜치를 만들었을때 생성되는 기본 브랜치 이름이다.
git init명령을 실행했을 때, 자동적으로 시작하는 브랜치가 바로 master이다.
특별히 어떤 작업이나 능력이 있는 것이 아니다.
생성하는 여타의 다른 브래치와 마찬가지로, 같은 능력과 같은 명령어들을 갖고 있다.
다른 점은, 우리가 만든 게 아니라는 것 뿐이다.
Git의 브랜치는, 생성되자마자 처음 커밋한 곳을 master브랜치로 지정한다.
이후 커밋을 만들면 master브랜치는 자동으로 가장 마지막 커밋을 가르킨다.
Git 버전 관리 시스템에서 master브랜치는 특별하지 않다. 다른브랜치와 다른 것이 없다는 것이다. 하지만 모든 저장소에서 master브랜치가 존재하는 이유는 git init 명령으로 초기화할 때 자동으로 만들어진 이 브랜치를 다른 이름으로 변경하지 않기 때문이다.
깋과 깃허브의 기본 브랜치 이름은 오랫동안 master였지만, 최근 들어 master에서 main으로 바꿨다. 하지만 깃에서는 여전히 master이다.
따라서, 예전 문서를 참고 할때 master라는 이름이 있으면 깃허브에서는 main이라고 보면 된다.
master브랜치는 특별한 것이 없다.
우리의 코드 베이스의 원본처럼 취급하기만 한다.
따라서 피쳐 브랜치를 만들어서 어떤 것을 제작하고 master브랜치에 merge하는 것으로 한다.
예를 들면, 아래와 같다
브랜치 생성에 대해 알아보기 전에 알아야 할 개념이 한 가지 더 있다.
위에 있는 HEAD이다.
git log를 살펴 봤을때, 위에 있는 가장 최근 커밋에서 Head -> master를 볼 수 있다.
깃 용어 중의 하나이고, 특히 저장소에서 현재 우리의 위치를 가리키는 포인터이다.
즉, 어떤 작업들 중 마지막 작업을 가리키는 포인터 또는 레퍼런스이다.
브랜치는 책갈피와 비슷하다. 책의 여러 위치에 다양한 북마크를 가질 수 있다.
이 북마크는 한번에 하나만 오픈이 가능하다. (동시에 북마크 두개를 보는 사람은 없기 떄문에...)
브랜치도 단지 한 페이지만 읽히거나 보여질 수 있다.
북마크한 페이지가 펼쳐졌다. 이것이 바로 HEAD가 가리키는 것이다.
HEAD는 보거나 확인하고 있는 현재 위치를 말하는 것이다.
HEAD는 언제나 master 브랜치에서 가장 최근에 커밋한 브랜치를 가르킨다.
즉, HEAD는 특별한 변경이 없는 이상 9가장 최근에 커밋한 master를 가리키며, 여기에 있는 화살표의 의미가 그런것이다.
밑에 있는 commit 하나하나 전부 마스터이고, HEAD는 브랜치 포인터를 가르킨다.
아래와 같이, HEAD를 변경 할 수도 있다.
정리하자면
- HEAD는 브랜치 포인터에 대한 레퍼런스 포인터이고 브랜치 포인터는 현재 브랜치가 있는 위치이다.
- 여러 개의 브랜치를 가질 수 있고, 각 브랜치는 브랜치 레퍼런스를 갖는다.
아래에서 처럼, Master브랜치에서 DarkMode를 만드는 실험적인 Branch를 만들면, Head가 그쪽을 가르킨다.
브랜치와 관련된 첫 명령어중 하나이다
git branch
이 명령은 저장소에 있는 현재 존재하는 브랜치 목록을 보여준다.
새 브랜치를 생성하거나 다른 브랜치로 이동하지는 않는다.
아직 새 브랜치를 만들지 않았기 때문에 master 브랜치 외에는 아무 것도 보이지 않는다.
git branch를 실행하면, master브랜치 하나를 볼 수 있고, 빠져나가려면, git log와 마찬가지로 q를 입력하면 된다.
만약, 다른 브랜치가 생성된 상태였다면 다른 브랜치들도 출력되고, 현재 위치한 브랜치는 위와 같이 별표시가 좌측에 있고, 초록색 글자로 나온다.
첫 브랜치를 만드는 방법에 대해 알아본다.
git branch < branch-name >
위 명령어와 비슷하게 생겼지만 branch-name만 추가하면 된다.
이 명령어는 새 브랜치를 만들어 주는 것이지, 그 브랜치로 이동하는 것이 아니다.
예시로 들기 위한 그림은 다음과 같다.
처음엔 master브랜치에 있다.
HEAD는 master브랜치를 가리키고 있으며, master 브랜치에 2개의 커밋이 있다.
git brach bugfix 명령을 실행하면
위와 같이 bugfix라는 새 브랜치가 생성된다. 현재 커밋을 가리키는 HEAD를 기준으로 생성된다. 이제 새 브랜치가 생겼고, 그 브랜치로 이동하지 않았기 때문에 아직 master에 있다.
이제 실습을 위해, 별도의 저장소를 만들어 해당 위치해서 실습해본다.
그 뒤에, playlist.txt를 수정하고 커밋을 해준다.
그 뒤에, git log를 살펴보면 HEAD포인터는 master를 가리키고 있으며 2개의 커밋이 있다.
이제 새로운 브랜치를 만들어본다.
만들기 전에, 먼저 현재 브랜치가 어떤것이 있는지 살펴보면 master밖에 없다는 것을 알 수 있다.
브랜치 oldies를 만든 후, git status를 보면, 여전히 master branch에 위치한 것을 알 수 있다.
또한, git branch 입력 시, oldies branch가 생성된 것을 볼 수 있다.
하지만 아직 HEAD가 oldies를 가르키지는 않는다.
즉, 두 개의 브랜치는 모두 같은 커밋을 참조하고 있으며 우리는 master브랜치에 있다는 것을 알 수 있다. 밑에와 같은 상태인 것이다.]
(Bugfix대신 oldies)
브랜치 이동을 위한 명령으로 git switch가 있다.
git switch branch-name
브랜치간의 이동을 위해 사용하는 명렁어
위 처럼, git switch bugfix를 실행하면, HEAD는 bugfix 브랜치를 가르키게 된다.
git switch oldies를 하면, master에서 oldies로 바뀐다.
git log와 git status를 보면 oldies로 이동한 것을 볼 수 있다.
여기서 playlist를 수정한다음 add, commit을 하고 log를 살펴보면 HEAD가 oldies를 가르키고 있는 것을 볼 수 있다.
우리가 최근 작업한 것이 oldies이기에 그런것이다.
하지만 이제 master브랜치는 뒤로 밀려났다.
하지만 master는 북마크처럼 남아서 여전히 참조 가능하다.
그리고 우리는 oldies 브랜치에 있다.
하지만 git switch 명령으로 달느 브랜치로 이동할 수 있다.
master브랜치로 이동하면, playlist가 master브랜치에 존재했던 상태로 돌아간다.
(즉, 수정하기 전 상태로 돌아간다.)
깃 로그를 살펴보면, 이렇게 되있는 것을 볼 수 있다.
또 다시 git switch oldies를 하면 log가 변한 것을 볼 수 있다.
위 명령어로 브랜치를 생성할 때, 현재 위치한 헤드를 기반으로 브랜치를 생성한다.
위에 파일을 아래와 같이 바꾼다.
그 다음, add와 commit을 동시에 하는 명령어를 입력한다.
그 다음, georges라는 브랜치를 생성하고
로그를 살펴보면 oldies, georges 두개가 모두 같은 커밋을 참조 하는 것을 볼 수 있다.
그 다음, georges로 스위치를 한 후에 보면
HEAD가 georges를 가르키는 것을 볼 수 있고, 이전 oldies에 있던 모든 커밋들은 이제 georges에 있다.
다시 playlist에 George Michael 노래 두 개를 추가하고, add, commit을 한 뒤에
git log를 살펴보면
HEAD는 현재 작업하고 있는 georges를 가리키고 있고, Georges에는 1개의 커밋만이 존재하고, oldies 브랜치는 이제 뒤에 남겨진 것을 볼 수 있다.
이제 oldies로 switch를 하면
다음과 같이 돌아가는 것을 볼 수 있다.
다시 goerges로 스위치를 해주면 아래와 같이 바뀐다.
branch가 georges에 있는 상테에서, ABBA의 노래를 삭제한 뒤에 add, commit를 한다.
이제 git log를 살펴보면
georges 브랜치에 새로운 커밋과 oldies 브랜치에 있던 모든 커밋들이 보인다.
이 분기한 시점에서, oldies에서 더 많은 작업을 해도 georges에는 영향이 없다.
여기서, master 브랜치에 돌아가면은
이렇게 표시 되고, 여기서 새로운 branch인 emptyplaylist 만들고 스위치를 한다.
플레이리스트를 비우고 커밋을 한뒤에
로그를 살펴보면 아래와 같이 나타난다.
작업하는 브랜치가 어디에서 분기된 것인지가 매우 중요한 것을 보여주었다.
브랜치 이동에 사용할 수 있는 다른 명령어에 대해 다룬다.
git checkout [branch-name]
git switch [branch-name] 명령과 동일한 작업을 할 수 있다.
깃에서 많은 작업을 하지만, 많은 사용자들이 혼란스러워하고 너무 많은 작업을 수행한다고 생각해서 깃은 switch 명령을 도입했다.
즉, 이 명령은 좀 더 구식 방식이다.
위를 살펴보면, checkout으로 switch와 동일하게 기능이 가능하였다.
브랜치를 만듬과 동시에 스위치를 할 수 있는 명령어
활용을 해보기 위해, master브랜치에서 새로운 브랜치를 만들어본다.
이것과 같은 명령어로는 git checkout -b [branch-name] 이 있다.
브랜치에서 작업을 했지만, 아직 커밋은 실행하지 않았을 경우
oldies브랜치로 이동한 다음, 다음과 같이 Van Morrison노래를 두 곡 추가해서 playlist파일을 수정한다.
그런 다음, add나 commit을 하지 않고 emptyplaylist로 브랜치를 스위치해본다.
커밋되지 않았다는 오류가 뜬다.
위에서 나오는 경고는, 지금 여기서 했던 작업들은 아직 커밋되지 않았기 때문에 다른 브랜치로 이동하려고 하면 사라질 것이라는 뜻이다.
따라서, 변경사항을 커밋하거나 임시로 백업하라고 나오는 것이다.
(stash는 곧 배울 것이다.)
커밋을 하고, 스위치를 하면 정상적으로 작동 하는 것을 볼 수 있다.
하지만, 커밋이 되지 않더라도 파일이 충돌되지 않으면 아무 문제 없이 작동하는 것을 볼 수 있다.
(oldies브랜치엔 chicken.txt파일이 존재하지 않으므로, 파일이 충돌하지 않는다.)
하지만, git status를 입력해 보면, untracked file이라고 나오는 것을 볼 수 있다.
그래서 변경사항을 만들 때 마다 브랜치 이동 전에 항상 커밋을 하는 것을 추천한다. (stash를 해도 된다.)
git branch -d [branch-name]
위 명령어는 브랜치를 삭제한다.
하지만, 위처럼 자신이 현재 위치한 브랜치는 삭제하지 못하며, 병합되지 않은 브랜치는 -d로 삭제되지 않는다.
git branch -D [branch-name]
- --force 옵션을 추가한 것으로, 병합 상태에 상관 없이 브랜치를 강제 삭제한다는 것이다.
git branch -m [branch-name]
- m은 move의 약자이다.
- 자신이 이름을 변경할 브랜치에 위치한 상태에서 변경할 이름을 입력하면 된다.
위에 실습을 보면, recentish-music이 2000s로 바뀐 것을 알 수 있다.
Moderat 노래 두 개를 추가하고, 커밋을 한 뒤 로그르 살펴보면
recentish-music브랜치는 더이상 존재 하지 않고, 2000s브랜치만 존재 하는 것을 볼 수 있다.
이번 섹터는 100퍼센트 선택사항이다. 만약 보고 싶지 않으면 넘어가도 된다.
HEAD가 어떻게 작동하는지, 그것이 참조하는 브랜치를 가리키고 각 브랜치 레퍼런스는 커밋을 참조한다는 사실에 대한 증거를 보여준다.
커밋 id 앞자리를 기억해두자 (2c90)
이제 .git이라는 숨은 디렉토리에 들어가보자.
디렉토리 안에 HEAD가 존재한다.
HEAD를 살펴보기 위해, cat HEAD 명령을 실행하면, 다른 것을 참조하고 있는 것을 알 수 있다.
간단히 말해서, HEAD는 master브랜치를 가리키고 있다.
만약, 다시 RoadtripPlaylist로 돌아가서 git switch oldies를 실행한 뒤에 다시 돌아온다면
oldies를 참조하는 것을 볼 수 있다.
(위 처럼 디렉토리를 왔다갔다 하는 것 보다는 아래와 같이 하는게 편하다.)
그 다음으로, refs/heads를 살펴보면 각 브랜치의 파일이 있는 것을 볼 수 있다.
Master파일을 보면, 다음과 같이 되어있는 것을 볼 수 있다.
위와 같이 [2c90..]로 시작하는 커밋이고, master branch가 흔적을 남긴 곳이고 master 브랜치의 북마크이다.
heads안에 파일들은 커밋 해시를 저장하고 있다.