git branch 명령어 | 브랜치 생성, 삭제, 변경, 확인, 이름 변경, 옵션
이번 포스팅은 branch에 대해 제대로 이해하고, git branch
명령어를 이용한 새 브랜치 생성, 삭제, 변경, 확인, 이름 변경 그리고 기타 옵션들에 대해 다룹니다.
1. git branch 제대로 이해하기
branch 는 Git을 이용한 협업에서 가장 핵심이 되는 기능입니다. 기존 파일 시스템에서 같은 시간에 같은 파일을 수정하기 위해서는, 사본을 만들어 따로 수정한 후 다시 수동적으로 합치는 방법 밖에 없었습니다. Git은 branch 기능을 통해 마치 멀티버스처럼 동시간대에 같은 파일에 대한 서로 다른 조작을 가능하게 합니다.
이처럼 유용하게 사용할 수 있는 브랜치 기능은 생각보다 단순한 원리를 이용합니다. 이전 git add, git commit 포스팅에서, 하나의 커밋에 해당하는 정보를 저장하는 commit object 는 부모 커밋에 대한 ID를 가진다고 했습니다. 커밋 히스토리는 결국 각 커밋이 가진 부모 커밋 ID 에 의해서 이어지는 것이고요.
브랜치는 이러한 커밋 히스토리 중 가장 최근 커밋을 가리키는 이름표에 불과합니다.
우리가 main
브랜치에서 작업을 한다면, main 이라는 브랜치 이름은 현재 커밋 히스토리의 마지막 커밋 ID를 갖고 있습니다.
다음 이미지와 같습니다.
커밋 B는 커밋 A의 ID인 2b89
를 알고 있기 때문에, 두 커밋은 히스토리로 연결될 수 있습니다.
그리고 main
이라는 브랜치 이름이 이 히스토리의 가장 마지막 커밋인 커밋 B의 ID 991b
를 알고 있어서 우리는 현재 브랜치를 main
이라고 부릅니다.
만약 현재 브랜치에서 새로운 커밋을 생성한다면 main
이름표에 적힌 마지막 커밋 ID 가 새로운 커밋 ID로 변경됩니다.
아래 이미지와 같습니다.
이처럼 branch기능을 구현하기 위해 사용되는 정보는 마지막 커밋 iD 하나뿐입니다. 그리고 다음 섹션에서 살펴볼 브랜치 변경 역시, 결국 브랜치 목록에 적힌 ID에 따라 해당 커밋으로 이동하는 것에 불과합니다.
만약 새로운 브랜치를 생성하고 해당 브랜치에서 새 커밋을 생성한다면 다음 이미지처럼 이해할 수 있습니다.
main
브랜치에서 topicA
라는 새로운 브랜치를 생성하면 main
과 topicA
브랜치 모두 v274
를 가리키게 됩니다. 이 때, topicA
브랜치에서 새 커밋을 생성하면 topicA
브랜치는 커밋 D의 ID 1g8c
를 가리키도록 변경됩니다.
이 상황에서 main
브랜치로 변경하면 커밋 C로, 다시 topicA
브랜치로 변경하면 커밋 D로 이동하는 것입니다. 브랜치는 마지막 커밋 ID에 대한 이름표라는 것, 꼭 기억하고 넘어가겠습니다.
2. 로컬, 원격 branch 목록 조회 확인
현재 로컬 리포지토리의 모든 브랜치를 확인하는 명령어는 다음과 같습니다.
$ git branch
이 때, *
표가 붙어 있는 브랜치가 현재 작업 브랜치입니다. 실행 결과는 다음과 같습니다.
목록 조회를 위한 git branch
명령어는 -r
옵션, -a
옵션을 사용할 수 있습니다. 각각 원격 브랜치만 출력하거나 로컬과 원격 브랜치 모두를 출력할 때 사용합니다.
다음과 같이 사용합니다.
3. 새 branch 생성
현재 branch 와 같은 커밋을 가리키는 새 branch를 만들기 위해서는 3가지 명령어를 사용할 수 있으며, 약간의 차이점이 존재합니다.
우선 아래 명령어는 가장 기본적인 브랜치 생성 명령어입니다.
$ git branch <new-branch-name>
2번째 명령어는 브랜치를 만들고나서 바로 해당 브랜치로 이동하는 명령어입니다. 생성 후 이동하는 과정 하나를 스킵할 수 있습니다.
$ git checkout -b <new-branch-name>
마지막 명령어는 checkout
보다 최신 명령어이며, 같은 결과를 냅니다. 가장 추천하는 방법입니다.
$ git switch -c <new-branch-name>
실행 결과는 다음과 같습니다.
설명한대로 새로운 브랜치를 생성한 후, 해당 브랜치로 변경되었습니다.
4. 원격 branch 로컬 환경에 복사
원격 리포지토리에 생성된 브랜치를 로컬 환경에 복사할 때는, checkout
혹은 switch
명령어와 함께 -t
옵션을 이용합니다. 따로 새 브랜치 이름을 지정해주지 않으면 원격 브랜치 이름과 동일하게 복사됩니다.
$ git checkout -t <remote-name>/<branch-name>
혹은
$ git switch -c <new-branch-name> -t <remote-name>/<branch-name>
실행 결과는 다음과 같습니다.
원격 repo의 feature-a
브랜치를 트래킹하는 feature-a
브랜치가 로컬 환경에 생성되었습니다.
5. branch 변경 전환 이동
작업 중인 branch를 변경하기 위해서는 2가지 명령어를 사용할 수 있습니다. 바로 checkout 과 switch 입니다. checkout 은 전통적인 명령어로, 브랜치 뿐 만 아니라 commit, tag 등 다양한 기준으로 이동할 수 있는 방법입니다. 이에 반해, switch 는 비교적 최신 명령어이며, 오직 브랜치 조작만을 위해 만들어졌습니다. 안전한 git 사용을 위해 기능이 제한된 switch 명령어 사용을 추천합니다.
두 명령어의 사용 방법은 다음과 같습니다.
$ git checkout <branch-name>
혹은
$ git switch <branch-name>
실행 결과입니다.
6. branch 삭제, 삭제 취소 방법
Git 브랜치 삭제는 2가지 방법으로 나뉩니다. 이중 첫번째는 이미 merge 완료한 브랜치를 삭제하는 경우이고, 두번째는 merge하지 않은 브랜치를 삭제하는 경우입니다.
6.1. branch 삭제
merge 완료한 브랜치를 삭제하는 명령어는 다음과 같습니다. 내가 현재 작업 중인 브랜치는 삭제할 수 없으니 다른 브랜치로 이동한 후 입력해주세요.
$ git branch -d <branch-name-merged>
이 경우, 삭제하는 브랜치에 속했던 커밋 중 마지막 커밋 ID 를 merge commit 이 부모 커밋 ID 로 가지고 있습니다. 따라서, 브랜치에 속했던 모든 커밋들은 이 repo 의 커밋 히스토리에 남게 됩니다.
다음은, merge 완료하지 않은 브랜치를 삭제하는 명령어입니다.
$ git branch -D <branch-name-not-merged>
이 경우에는, 삭제하는 브랜치에 속했던 커밋을 가리키는 포인터가 사라집니다. 따라서, 해당 브랜치에 속했던 커밋들에 접근할 수 없게 되는데요. 이러한 상황을 dangling 혹은 orphaned commit 상태라고 합니다. 이렇게 접근 불가한 커밋들은 Git 의 가비지 컬렉터가 알아서 정리해줍니다.
먼저 merge 완료한 브랜치 삭제 결과를 보겠습니다.
위에 있는 git log graph 는 feature-c
브랜치를 develop
브랜치에 merge한 것을 보여줍니다.
이 상태에서 feature-c
브랜치를 삭제했습니다. 그후 다시 로그 그래프를 출력하니 feature-c
브랜치는 사라졌지만, 브랜치에 속한 커밋들은 히스토리에 남아있습니다.
이는 merge commit인 0dd7b0b
커밋이 develop
브랜치의 80d10f1
커밋과 feature-c
브랜치의 8480ae1
커밋의 ID를 모두 가지고 있기 때문입니다.
다음은, merge하지 않은 브랜치 삭제 결과입니다.
위에 있는 로그 그래프를 보면, develop
브랜치에서 새로운 feature-d
브랜치를 생성하고 새 커밋을 만들었습니다. 이후 merge하지 않은 상태에서 feature-d
브랜치를 삭제하니, 로그 그래프에서 사라진 것을 확인할 수 있습니다.
6.2. branch 삭제 취소
마지막으로, 실수로 삭제한 branch를 되돌리는 명령어를 알아보겠습니다. 눈썰미가 좋은 분들은 아셨겠지만 branch 삭제 명령어는 성공 메시지와 함께 해당 branch가 가리키던 마지막 커밋 ID를 출력합니다.
Deleted branch feature-d (was 3a31806)
메시지의 3a31806
처럼 말입니다. 위 화면에서 확인해보세요.
branch 삭제를 취소하려면 이와 같은 커밋 ID를 이용해야 합니다. 명령어는 다음과 같습니다. <base-commit-id>
부분에 커밋 ID를 넣어줍니다.
$ git branch <branch-name> <base-commit-id>
이 명령어로 위에서 삭제한 2개의 브랜치를 되돌려보겠습니다.
커밋 히스토리는 다음과 같습니다.
feature-c
, feature-d
브랜치가 이전 위치에서 부활한 것을 확인할 수 있습니다.
6.3. remote branch 삭제
모든 Git 호스팅 서비스에서 원격 브랜치 삭제를 UI로 지원하지만 명령어로 삭제할 수도 있습니다.
명령어는 다음과 같습니다.
$ git push <remote-name> --delete <branch-name>
실행 결과입니다.
만약 로컬 환경에 삭제한 원격 브랜치를 트래킹하는 브랜치가 존재한다면, 이 로컬 브랜치는 함께 삭제되지 않습니다. 섹션 6.1 에서 알아본 명령어로 삭제해주세요.
7. 마치며
git branch
명령어는 한 프로젝트에 여럿이 동시에 작업을 수행하는 기초가 되는 명령어자, 이러한 개념을 담고 있습니다. 이 포스팅이 branch를 제대로 이해하고 사용하는 데 도움이 되었길 바랍니다.