통합개발도구/Git & Git-Hub

4. Branch

Zoo_10th 2024. 6. 7.

1. Branch 사용하기

개발 작업을 할 때, 개발자들은 작업 레파지토리에서 소스 코드를 공유한다. 연관성이 없는 기능을 개발한다고 할 때 어떤 개발자는 A 기능을 작업하고 또 다른 개발자는 B 기능을 맡아 작업한다고 가정해보도록 한다.

만약 A 작업이 다 끝난 뒤에 B 작업을 수행한다면 연관성이 없는 기능 단위의 작업을 비효율적으로 하고 있는 것이다. 별도로 작업하여 합치는 방안이 가장 좋다. Git에서는 브랜치와 머지라는 명령으로 이것을 가능하게 한다.

브랜치는 독립적인 작업을 할 수 있는 공간이다. A 기능을 A 브랜치에서 작업하고, B 기능을 B 브랜치에서 작업하면, 서로 다른 독립적인 공간에서 작업하는 것이기 때문에 서로에게 영향을 주지 않고 작업할 수 있다. 메인 작업 공간의 코드를 복사한 개별적인 작업 공간을 만들고 거기서 각각의 기능 개발을 진행한다. 그리고 작업이 완료되었을 때, 코드를 합치면 된다.

아래 그림의 개리는 기본 브랜치에서 작업중이다. 그리고 개리1, 개리2, 개리3 이라는 커밋을 남기고있다. 빙키는 개리의 프로젝트에 참여하려 한다. 개리가 작업을하던 내역을 기본브랜치에서 pull받고 개리3을 커밋한 부분에서 작업 공간을 기능 브랜치로 분리한다. 빙키는 이제 분리된 작업공간(기능 브랜치)에서 자신의 커밋을 남기며 작업을 독립적으로 진행한다.

개발자는 기능 브랜치에서 작업한 내용을 기본 브랜치로 바로 커밋을 날릴 수 있고 코드를 병합(merge)하고 업데이트 할 수 있다. 브랜치로 작업을 하면 브랜치 단위로 업데이트가 되기 때문에 충돌이 일어나는 일을 방지하기 좋다.

만약 서로 같은 부분을 다르게 수정하여 합치면 어떻게 될까? 충돌이 난다. 충돌이 나면 둘 중 하나를 선택하라는 선택이 뜬다.
되돌릴 수도 있다.

git에서의 기본 브랜치는 master 브랜치(GitHub은 main) 이다. 기본브랜치는 git 저장소를 초기화할 때 자동으로 만들어진다. 이때, 'HEAD'라는 특수한 포인터가 있다. 이 포인터는 지금 작업 중인 브랜치를 가리킨다.

git config --global init.defaultBranch main
명령을 통해 git에서도 GitHub처럼 기본 브랜치를 main으로 사용할 수 있다.

하나의 기능 개발이 완료되면 특정 브랜치의 내용들을 main 브랜치에 합친다. 또 새로운 작업을 하려고 하면 main 브랜치에서 다시 새로운 feature 브랜치를 생성하고 작업한다.

특정 기능을 작업하고 있는데 급하게 버그를 수정해야 하는 경우가 발생한다. 이런 경우 현재의 작업 상태를 임시로 커밋해두고 이전 기능 작업 중인 상태로 브랜치(작업폴더)를 변경할 수 있다.

버그 패치용 브랜치를 만들고 수정 작업을 한다. 이후 작업이 완료되면 버그 패치용 브랜치의 추가된 변경 내역을 main 브랜치에 합칠 수 있다. 이런 과정을 거치면 main 브랜치는 가장 최근에 배포한 소스코드의 커밋을 가리키고 있게 된다.

1-1. 브랜치 사용 방법

1) 현재 브랜치 목록과 현재 브랜치 확인

$ git branch

개리1, 개리 2, 개리 3, 개리 4는 커밋 메시지이다. 개리 4가 담고 있는 내용이 가장 최신의 상태라고 할 수 있다. HEAD 포인터가 가리키고 있는 브랜치가 main이기 때문에 $ git branch를 하면 * main가 출력 된다.

2) branch 만들기

브랜치를 현재 시점에 만들 수 있다. 

$ git branch Gary
$ git branch Gary main #이렇게 입력할 경우 main에서 파생되는 브랜치를 만든다.

1-2. 기본 브랜치(main, master)

git에서의 기본 브랜치는 master이고 GitHub에서의 기본 브랜치는 main이다.

git init 명령을 통해 초기화하고 레포지토리에 연결하는 과정(해당 챕터에서 진행하는 과정)을 진행하게 되면 기본 브랜치는 master가 된다. 앞에 언급된 명령어 git config --global init.defaultBranch main 로 설치 시 또는 설치 후 설정을 통해 기본 브랜치 이름을 바꿀 수도 있다. 깃허브에서 제공하는 초기화 설정을 사용하거나 가이드라인을 따라 진행한다면 기본 브랜치가 main이 된다.

README.md file 초기세팅
git-hub 레포지토리 연결 가이드라인

2. Branch 이동/변경, 파일 복원하기

2-1. checkout

checkout은 브랜치 변경 또는 작업 트리 파일 복원을 할 수 있다. 하지만 기존의 checkout이 가진 기능이 너무 많았다. 때문에 Git 2.23에서 checkout을 대신해 switch와 restore가 도입되었다.

checkout을 통해 브랜치를 이동하여 사용할 수 있다. 호텔 체크아웃을 생각하셔서 브랜치를 떠난다고 생각하면 안된다. 사용할 브랜치를 지정하는 것이 checkout이다.

$ git checkout Gary

새로운 내용을 추가하고 커밋한다.

$ echo 'hello branch' >> branch.txt
$ git status
$ git add branch.txt
$ git commit -m "개리 5"

상대방이 원격 저장소에서 pull을 받는다.

$ git pull

git log --all --decorate --oneline --graph 명령어를 사용하면 모든 컴밋을 그래프로 볼 수 있다.

push를 할 때 다음과 같은 애러가 뜬다면 아래 명령어를 그대로 입력해야한다.

git push를 하니 에러가 발생한다. 에러가 발생하는 이유는 upstream 브랜치를 설정하지 않았기 때문이다. 그렇기 때문에 git push --set-upstream origin branch_name 명령어를 이용하여 해당 명령어 이후부터는 원격 저장소에 Binky의 브랜치를 만들어 push 하겠다는 뜻이다.

 git push vs git push <원격저장소명> <브랜치명>
왜 git push origin main일까? 그냥 git push하면 안되나요? 라고 생각하실 수도 있다.

git push <원격저장소명> <브랜치명> 는 어느 원격 저장소의 어느 브랜치에 push할 지 전달한다.
git push 는 할 때에는 이미 연결된 곳에 push할 수 있지만, 원격 저장소에 해당 브랜치가 없는 경우에는 git push -u origin <브랜치명> 을 실행해야 이후에 간단히 push할 수 있다. -u 옵션이 --set-upstream 이다.
  • 여기서 origin은 키워드가 아니다. one, two등에 이름으로 할 수 있다. 이는 여러 원격 저장소를 연결할 수 있기 때문이다.
  • 위 내용에 이어 main이 어느 원격 저장소(GitHub인지 GitLab인지 또는 그 외인지)의 main인지 알 수 없기 때문에 설정해주는 설정이다. </aside>

2-2. switch

브랜치를 변경한다.

$ git switch Gary

2-3. restore

restore는 파일의 수정 내용 복원과 add 를 통해 스테이지에 올린 파일을 빼낼 때 사용한다.

우선 파일을 생성한 후 커밋을 한다.

$ touch README.md
$ vi README.md //i->작성 후->Esc->:wq
$ git add .
$ git commit -m "add file"
$ git status

이후 해당 파일을 수정한 후에 저장을 하고 상태를 보도록 한다. 아래 순서대로 진행면 된다.

1) 아래의 명령어 입력

$ vi README.md

2) 아래 순서에 따라 순차적으로 편집

i -> 수정 후 -> Esc -> :wq

modified 파일이 있다고 나온 것을 볼 수 있다.

이때, 파일 변경 내역을 modified 파일에서 unmodified 파일로 되돌리는 방법은 두 가지가 있다.

3) modified 파일에서 unmodified 파일로 되돌리는 방법

①  restore을 이용하여 변경 사항을 되돌리기

$ git restore README.md

② checkout을 이용하여 파일 변경 내역을 되돌리기

git checkout -- filename 은 해당 파일 내용이 최신 커밋 전으로 돌아가도록 한다. 이때, checkout으로 지워진 내용은 커밋을 하지 않았기 때문에 다시 복구할 수 없다.

$ git checkout -- README.md

modified 파일이 없는 것을 볼 수 있다.

파일을 열어 확인한 결과다.

hello world
Byebye

checkout — filename 전

hello world

checkout — filename 후

4) 스테이지 올린 것을 빼는 방법

$ git add .
$ git status

① restore 명령어를 이용하여 빼기

$ git restore --staged README.md

② reset 명령어를 이용하여 빼기

$ git reset HEAD README.md

상태를 확인해 보면 스테이지에 올라가 있지 않은 것을 확인할 수 있다.

3. Branch 삭제/복구하기

3-1. branch 삭제

특정 브랜치를 삭제하는 명령어이다.

$ git branch -D <삭제할 브랜치명>

Gary 브랜치를 git branch -D Gary 명령어로 삭제한다.

삭제한 뒤, git branch 명령어를 통하여 제대로 삭제했는지 확인할 수 있다. 브랜치 목록에 main만 있으므로 Gary 브랜치가 삭제되었음을 알 수 있다.

3-2. branch 복구

삭제한 브랜치를 복구하는 것은 2단계로 나눠서 진행할 수 있다.

1) git reflog로 복구 시점 확인

먼저, 삭제한 브랜치를 어떤 시점으로 복구할 것인지 알아야한다. 삭제한 브랜치가 남겼었던 커밋 중 어떤 상태로 돌아갈 지를 찾아서 커밋 해시값을 가져와야 한다. 이를 위해서 모든 참조 목록을 확인 할 수 있는 git reflog명령어를 입력한다.

$ git reflog

reflog는 모든 참조 내역들을 뜻한다. main 브랜치에서 어떤 브랜치로 참조를 했는지, 어떤 커밋을 날렸는지 등 모든 내역들을 git reflog를 통해 확인할 수 있다.

Gary 브랜치를 git branch -D Gary 명령어로 삭제 한 뒤, 복구 시켜본다.

git reflog 를 하면 다음과 같이 참조 목록들을 확인 할 수 있다. Gary 브랜치가 Gary- 1 번째 커밋 커밋 메시지를 날렸던 시점으로 복구하기 위해 해당 커밋 메시지를 HEAD가 가리킨 시점의 해시 값을 찾는다.

2) git checkout으로 브랜치 복구

브랜치를 복구하는 명령어는 다음과 같다.

$ git checkout -b <삭제한 브랜치명> <커밋 해시값>

git reflog로 삭제한 브랜치의 마지막 커밋 해시값을 확인한 뒤, 이를 이용해서 브랜치를 복구시킬 수 있다.

위의 명령어를 실행하면 Gary 브랜치로 위치가 변경된다.

4. merge(합병)하기

두 branch로 나누어 작업했던 것을 병합하는 명령어다.

$ git checkout main
$ git log
$ git merge binky
$ git log

merge가 완료되었으면 push 까지 해주셔야 원격 저장소에 반영이 된다.

$ git push origin main

위에 binky 브랜치를 merge한 후에 gary의 브랜치를 merge해 보도록 하겠다. 만약, 두 브랜치가 같은 곳을 수정했다면 충돌이 일어나지만 지금은 다른 곳을 수정했다는 가정하에 진행하도록 하겠다.

$ git merge Gary
$ git push origin main

5. conflict (충돌)

개리 브랜치와 main 브랜치 둘 다 README.md에서 작업을 하는데 서로 변경 내역이 다르다고 가정해 보도록 한다.

이때, 개리 브랜치와 main 브랜치의 작업내역이다.

hello world
hello Gary

Gary브랜치

hello world
hello binky

main 브랜치

merge할 때 두 브랜치가 같은 곳을 수정했다면 충돌이 일어난다. 이때 충돌난 시점을 찾아 수동으로 고쳐주어야 한다.

<<<<<<< HEAD (Current Change)
hello world
hello binky
=======
>>>>>>> branchName (Incoming Change)
hello world
hello Gary

conflict는 두가지 변경 내역을 비교한 다음에 원하는 코드를 남기는 것이다.

hello world
hello binky Gary

이후 add > commit > push 를 하면 된다.

5-1. VSC에서 conflict (충돌) 해결하기

visual studio code에서는 충돌에 대해 좀 더 자동화된 도구를 제공한다.

아래와 같이 충돌이 났을 때 현재 코드를 유지할지, 머지된 코드를 반영할지 클릭으로 처리할 수 있다.

※ VSC에서 git bash 사용하는 방법

 1) 디폴트로 설정하기

Window VSC에서 Ctrl + Shift + P
Mac VSC에서 cmd + shift p

Select Default Profile 입력 후 선택

Git Bash 선택

2) + 버튼을 클릭하여 git bash로 열기

728x90

'통합개발도구 > Git & Git-Hub' 카테고리의 다른 글

6. Pull Request  (0) 2024.06.07
5. Fork  (0) 2024.06.07
3. Git-hub  (0) 2024.06.07
2. Git  (0) 2024.06.05
1. Git & GitHub 기본 개념  (0) 2024.06.05

댓글