Skip to content
This page has been auto-translated and may contain errors.View in English

Git의 브랜치

docs.scrimba.com

weather-app 구축 중간에 5일 날씨 예보 기능을 추가해보고 싶습니다. 제대로 작동하기까지 몇 개의 커밋이 필요할 수 있으며, 그때까지는 미완성 코드가 이미 작동하는 앱 옆에 있고 싶지 않습니다. 브랜치는 Git이 이를 해결하는 방법입니다. 실험이 진행되는 별도의 작업 라인이며, main은 시작하기 전과 정확히 같은 방식으로 계속 작동합니다.

브랜치가 실제로 무엇인지

실제 작동 모습은 다음과 같습니다:

bash
$ git branch forecast
$ git switch forecast
Switched to branch 'forecast'

두 가지 명령: 첫 번째는 forecast라는 새 브랜치를 생성하고, 두 번째는 그 브랜치로 이동합니다. 여기서부터 forecast에서 만드는 모든 커밋은 forecast에 저장되고 main은 정확히 그 위치에 남아 있습니다.

**브랜치**는 커밋을 가리키는 이동 가능한 레이블입니다. 지금 mainforecast 모두 같은 커밋을 가리키고 있으며, 이는 git branch forecast를 실행할 때 서있던 커밋입니다. forecast에서 다시 커밋하는 순간 그 레이블은 새 커밋으로 앞으로 이동합니다. main은 직접 전환하고 거기서 커밋할 때까지 정확히 그 위치에 남아 있습니다.

git branch로 두 레이블을 모두 볼 수 있습니다:

bash
$ git branch
  forecast
* main

별표는 현재 위치한 브랜치를 표시합니다. 브랜치는 단지 커밋을 가리키는 이름일 뿐입니다. 이것이 전체 메커니즘입니다. 이 장의 나머지 모든 내용은 그 레이블을 이동시키는 변형입니다.

실제 프로젝트에서 브랜치 이름은 정보를 담고 있습니다. 일반적인 관례는 변경의 종류를 설명하는 짧은 접두사 뒤에 설명이 오는 것입니다: feature/five-day-forecast, fix/broken-date-picker, chore/upgrade-eslint. 일부 팀은 티켓 번호를 추가합니다(feature/wa-142-forecast). 어떤 관례를 선택하든 프로젝트 전체에서 일관되게 유지하여 누구나 브랜치를 열어보지 않고도 그 목적을 알 수 있도록 하세요.

이 이름들이 지원하는 워크플로는 단기 기능 브랜치입니다: 한 조각의 작업을 위한 브랜치를 생성하고, 커밋하고, 변경 사항을 검토받고 병합한 다음, 브랜치를 삭제합니다. 수주 동안 존재하는 브랜치는 main에서 크게 벗어나고, 최종 병합은 그 차이가 계속될수록 더 어려워집니다. 가장 건강한 브랜치는 며칠 내에 완료됩니다.

브랜치는 Git의 자체 기록 내에 숨겨진 한 커밋 해시를 보유한 작은 파일일 뿐입니다. 하나를 생성한다는 것은 그 한 줄을 쓰는 것을 의미하며, 이것이 git branch가 수년간의 이력이 있는 저장소에서도 즉시 완료되는 이유입니다. 그 같은 저렴함 때문에 이름 지정 관례와 단기 브랜치가 실제로 중요합니다: 오래된 브랜치를 삭제하는 것도 Git에 비용이 들지 않으므로 팀의 규율 외에는 버려진 브랜치가 쌓이는 것을 막을 수 없습니다.

Juno브랜치가 실제로 무엇인지git branch forecast는 현재 커밋을 가리키는 새 레이블을 생성하고, git switch forecast는 그 레이블로 이동시킵니다. 실제로 거기서 커밋할 때까지 파일에 대해 아무것도 변경되지 않습니다. 나는 브랜치를 커밋에 붙인 포스트잇으로 생각하기 좋아합니다: 추가하기 쉽고, 이동하기 쉽고, 끝났을 때 벗기기 쉽습니다.
Juno브랜치가 실제로 무엇인지 브랜치 이름은 포인터이므로 생성하는 것은 비용이 들지 않고 그 사이를 전환하는 것은 즉각적입니다. feature/five-day-forecast와 같은 작업을 설명하는 이름을 브랜치에 지정하고 단기로 유지합니다: 생성, 커밋, 병합, 삭제. 오래 유지되는 브랜치는 일상적인 병합을 실제 골칫거리로 만드는 것들입니다.
Juno브랜치가 실제로 무엇인지 브랜치는 정말로 커밋 해시를 보유한 작은 파일이며, 이것이 하나를 생성하는 것이 Git에서 가장 저렴한 작업 중 하나인 이유입니다. 이름 지정 관례와 단기 브랜치는 팀이 병렬 작업을 읽을 수 있도록 유지하는 방법입니다. Git 자체는 이 중 어떤 것도 강제하지 않습니다. 6개월 전의 버려진 브랜치를 충분히 정리했으니 이에 대해 확실한 의견이 있습니다.

브랜치 생성 및 전환

git branch forecast는 단독으로 레이블을 생성하지만 거기로 이동시키지는 않습니다. 대부분의 경우 둘 다 원하므로 git switch에는 바로가기가 있습니다:

bash
$ git switch -c forecast
Switched to a new branch 'forecast'

-c는 "create"를 의미합니다. git switch -c는 브랜치를 생성하고 그 브랜치로 이동합니다. 그 단일 명령이 새 작업을 거의 매번 시작할 때 사용하는 것입니다.

브랜치를 전환하면 파일이 표시하는 스냅샷이 변경됩니다. 시도해보세요. 아래의 echo 줄은 새 파일 src/forecast.js를 한 줄의 내용으로 생성하는 한 단계 방식이며, 나머지는 이미 알고 있는 명령입니다:

bash
$ git switch forecast
$ echo "// five-day forecast logic" > src/forecast.js
$ git add src/forecast.js
$ git commit -m "Start forecast module"
$ ls src
forecast.js  index.js
$ git switch main
Switched to branch 'main'
$ ls src
index.js

파일이 사라진 것이 아닙니다. forecast 브랜치에 있으며, main 브랜치의 스냅샷에는 절대 포함되지 않았습니다. forecast로 다시 전환하면 정확히 그대로 다시 나타납니다.

기존 코드와 튜토리얼에서 더 오래된 동사를 볼 수 있습니다: git checkout forecastgit switch forecast와 같은 작업을 합니다. checkout은 더 오래되었고 여러 작업을 수행합니다. 어떤 것을 주느냐에 따라 브랜치를 전환하거나 파일을 이전 버전으로 복원할 수 있으며, 명령 이름만으로는 어떤 것이 일어나려고 하는지 알 수 없습니다. switchrestore는 두 작업을 별도의 명령으로 분할하여 이름이 미리 알려줍니다: switch는 브랜치 사이를 이동하고 restore는 파일을 주어진 커밋에서의 모양대로 복원합니다. 더 새로운 동사를 사용하세요. 야생에서 checkout을 만날 때 인식하세요.

checkout은 주어진 것에 따라 수행할 작업을 결정합니다: 브랜치 이름은 브랜치를 전환하고, 파일 경로는 해당 파일을 복원하며, 이름이 둘 다 일치하면 Git은 어느 것을 의미했는지 추측해야 합니다. 그 추측이 바로 명령이 둘로 나뉜 이유입니다. switch는 오직 브랜치만 변경하고 restore는 오직 파일만 변경하므로 잘못된 경로는 더 이상 실수로 브랜치로 전환할 수 없습니다. 오래된 스크립트와 튜토리얼에서 checkout이 있을 것으로 예상하세요. 새로운 모든 것에 switchrestore를 작성하세요.

Juno브랜치 생성 및 전환git switch -c forecast는 한 단계로 브랜치를 생성하고 이동시키며, 거의 매번 사용할 것입니다. 브랜치를 전환하면 표시되는 파일 버전이 바뀌므로 한 브랜치에 추가된 파일은 다시 전환할 때까지 다른 브랜치에는 없습니다. 아무것도 손실되지 않으며, 다른 브랜치에 주차되어 있습니다.
Juno브랜치 생성 및 전환git switch -c name는 한 단계로 생성하고 이동합니다. 오래된 튜토리얼과 코드베이스에서 git checkout name이 같은 작업을 하는 것을 만날 것입니다. 이는 오래되고 과도하게 부하가 걸린 명령의 같은 아이디어입니다. 매일 switch를 사용하고 볼 때 checkout을 망설임 없이 읽으세요.
Juno브랜치 생성 및 전환checkout은 인수에 따라 브랜치 전환과 파일 복원을 모두 처리하며, 이것이 정확히 switchrestore가 제거되도록 분할된 모호함입니다. 오래된 스크립트와 튜토리얼에서 checkout을 읽을 것으로 예상하세요. 여전히 작동하지만 더 이상 기본적으로 작성할 명령이 아닙니다.

HEAD와 detached HEAD

Git은 **HEAD**라는 마커로 현재 위치를 추적합니다. 일반적으로 HEAD는 현재 브랜치를 가리키고, 그 브랜치는 커밋을 가리키므로 전환하거나 커밋할 때마다 HEAD는 자동으로 이동합니다. 브랜치 이름 대신 특정 커밋을 해시로 또는 태그(종종 릴리스를 표시하는 한 커밋에 고정된 레이블)로 체크아웃하면, HEAD는 그 브랜치 레이블 대신 그 하나의 커밋에 직접 첨부됩니다. 이 상태를 detached HEAD라고 합니다.

거기서 자유롭게 둘러볼 수 있으며, 심지어 커밋할 수도 있지만, 그 새 커밋은 아무것도 이름으로 가리키지 않습니다. 먼저 브랜치를 생성하지 않고 브랜치로 전환하면 다시 찾기 어려워집니다.

bash
$ git switch a1b2c3d
HEAD is now at a1b2c3d Add password strength meter

그 메시지 "HEAD is now at"은 Git이 브랜치 영역을 떠나 HEAD를 단일 커밋에 첨부했음을 알려주는 것입니다.

일상적인 작업에서 실수로 여기에 도달하는 일은 거의 없습니다. 가장 많이 일어나는 것은 오래된 태그나 특정 커밋을 체크아웃하여 코드가 해당 시점에서 어떻게 작동했는지 살펴볼 때 또는 빌드 도구가 정확한 하나의 커밋을 체크아웃하여 작업할 때입니다. 보고만 싶다면 괜찮습니다: 파일을 탐색하고, 앱을 실행한 다음, 완료되면 브랜치로 다시 전환하세요. detached 상태에서 유지할 가치가 있는 변경을 하면 전환하기 전에 브랜치를 생성하세요: 그 detached 상태에서 git switch -c fix/old-bug는 커밋에 실제 레이블을 제공하여 전환이 생존하도록 합니다.

detached HEAD에 남겨진 커밋은 전환하는 순간 삭제되지 않습니다. 그것은 도달 불가능해집니다: 여전히 저장되어 있지만, 더 이상 그 커밋을 가리키는 브랜치, 태그 또는 HEAD가 없습니다. Git은 그것들도 즉시 정리하지 않습니다. 그것은 reflog, HEAD가 가리켰던 모든 위치의 기록을 유지하며, 도달 불가능한 커밋은 일반적으로 Git이 완전히 삭제하기 몇 주 전까지 생존합니다.

이것은 복구할 실제 시간을 제공하지만 영구적이지는 않습니다. 전환하기 전에 브랜치를 만들면 detached 작업을 안전하게 유지합니다. reflog에서 커밋을 파고 꺼내는 것은 오늘 작동하지만 항목이 만료되고 커밋 해시는 그보다 오래 전에 마음에서 사라지므로 브랜치를 습관으로 만들고 reflog는 변경 사항 실행 취소에서 다룬 드문 경우에 대해 저장하세요.

JunoHEAD와 detached HEAD HEAD는 현재 서있는 커밋을 표시하며 일반적으로 어떤 브랜치를 타고 있든 그 브랜치와 함께 이동합니다. 브랜치 대신 특정 커밋을 체크아웃하면 detached HEAD를 얻으며, 거기서 만드는 새 커밋은 그것을 가리키는 브랜치 이름이 없습니다. 그런 일이 일어나고 그 작업을 유지하고 싶다면, 다른 곳으로 전환하기 전에 즉시 그 자리에 브랜치를 만드세요.
JunoHEAD와 detached HEAD detached HEAD를 태그나 오래된 커밋을 체크아웃하여 둘러볼 때 만날 것이 가장 같으며, 당신이 읽기만 하면 해롭지 않습니다. 유지할 가치가 있는 것을 커밋하는 순간 git switch -c를 그곳에서 바로 실행하여 다른 곳으로 가기 전에 브랜치를 제공하세요.
JunoHEAD와 detached HEAD 보통 HEAD는 브랜치를 가리키고, 그 브랜치는 커밋을 가리킵니다. Detached이면 HEAD는 커밋을 직접 가리키므로 거기서 추가하는 모든 것은 전환하면 그것을 붙잡는 브랜치 이름이 없습니다. reflog가 흔적을 남기기 때문에 완전히 사라질 일은 거의 없지만, 3주 후에 커밋 해시를 기억할 것으로 계산하지 마세요. 전환하기 전에 항상 브랜치를 만드세요.

여기서 갈 곳

이제 브랜치를 생성하고, 그 사이를 이동하고, main이 다른 곳에서 실험하는 동안 터치되지 않은 상태로 유지되는 방식을 보았습니다. 다음 질문은 브랜치의 작업이 main으로 어떻게 돌아가는지이며, 이것이 정확히 병합 및 충돌이 다루는 내용입니다. 이동하기 전에 커밋 이력을 읽는 것에 대한 복습을 원하면 이력git log, git show, 및 git diff를 통해 설명합니다.