WeniVooks

검색

알잘깔딱센 GitHub 핵심개념

Branch

1. Branch 사용하기

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

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

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

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

알잘딱깔센 GitHub

알잘딱깔센 GitHub

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

만약 서로 같은 부분을 다르게 수정하여 합치면 어떻게 될까요? 충돌이 납니다! 충돌이 나면 둘 중 하나를 선택하라는 선택이 뜨죠. 걱정하지 않으셔도 됩니다. 되돌릴 수도 있으니까요.

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

알잘딱깔센 GitHub

알잘딱깔센 GitHub

해당 책에서 나오는 예시에서 main 브랜치 또는 master 브랜치는 기본 브랜치를 의미합니다. master라는 단어가 노예제를 떠올리게 한다는 이유로 많은 코드에서 master 대신 main을 채택하고 있습니다.

git config --global init.defaultBranch main

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

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

알잘딱깔센 GitHub

알잘딱깔센 GitHub

알잘딱깔센 GitHub

알잘딱깔센 GitHub

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

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

지금부터 브랜치 사용 방법을 알아보겠습니다.

  • 현재 브랜치 목록과 현재 브랜치 확인

    $ git branch
    $ git branch

    알잘딱깔센 GitHub

    알잘딱깔센 GitHub

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

  • branch 만들기 브랜치를 현재 시점에 만들 수 있습니다. Gary 브랜치를 만들어 봅시다.

      $ git branch Gary
      $ git branch Gary
    $ git branch Gary main #이렇게 입력할 경우 main에서 파생되는 브랜치를 만듭니다.
    $ git branch Gary main #이렇게 입력할 경우 main에서 파생되는 브랜치를 만듭니다.
알잘딱깔센 GitHub
1.1 기본 브랜치(main, master)

앞에서 언급했듯, git에서의 기본 브랜치는 master이고 GitHub에서의 기본 브랜치는 main입니다.

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

README.md file 초기세팅

README.md file 초기세팅

git-hub 레포지토리 연결 가이드라인

git-hub 레포지토리 연결 가이드라인

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

2.1. checkout

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

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

$ git checkout Gary
$ git checkout Gary
알잘딱깔센 GitHub

알잘딱깔센 GitHub

새로운 내용을 추가하고 커밋해봅시다.

$ echo 'hello branch' >> branch.txt
$ git status
$ git add branch.txt
$ git commit -m "개리 5"
$ echo 'hello branch' >> branch.txt
$ git status
$ git add branch.txt
$ git commit -m "개리 5"
알잘딱깔센 GitHub

알잘딱깔센 GitHub

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

$ git pull
$ git pull
알잘딱깔센 GitHub

알잘딱깔센 GitHub

상대방이 브랜치를 생성하고 커밋을 한 경우입니다.

$ git checkout main
$ git branch binky
$ git checkout binky
$ git commit -m "빙키 1"
$ git checkout main
$ git branch binky
$ git checkout binky
$ git commit -m "빙키 1"
알잘딱깔센 GitHub

알잘딱깔센 GitHub

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

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

Untitled

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

Untitled

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인지 알 수 없기 때문에 설정해주는 설정입니다.
2.2. switch

브랜치를 변경합니다.

$ git switch Gary
$ git switch Gary
알잘딱깔센 GitHub

알잘딱깔센 GitHub

알잘딱깔센 GitHub

알잘딱깔센 GitHub

브랜치를 새로 만들어서 변경할 수도 있습니다.

$ git switch -c Gary
$ git switch -c Gary
알잘딱깔센 GitHub

알잘딱깔센 GitHub

알잘딱깔센 GitHub

알잘딱깔센 GitHub

2.3. restore

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

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

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

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

  1. 아래의 명령어 입력
$ vi README.md
$ vi README.md
  1. 아래 순서에 따라 순차적으로 편집
i -> 수정  -> Esc -> :wq
i -> 수정  -> Esc -> :wq

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

Untitled

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

  1. restore을 이용하여 변경 사항을 되돌리기
$ git restore README.md
$ git restore README.md
  1. checkout을 이용하여 파일 변경 내역을 되돌리기

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

$ git checkout -- README.md
$ git checkout -- README.md

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

Untitled

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

hello world
Byebye
hello world
Byebye
hello world
 
hello world
 

스테이지 올린 것을 빼는 방법은 두 가지가 있습니다.

$ git add .
$ git status
$ git add .
$ git status
Untitled
  1. restore 명령어를 이용하여 빼기
$ git restore --staged README.md
$ git restore --staged README.md
  1. reset 명령어를 이용하여 빼기
$ git reset HEAD README.md
$ git reset HEAD README.md
Untitled

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

Untitled

3. Branch 삭제/복구하기

3.1. branch 삭제

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

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

Gary 브랜치를 git branch -D Gary 명령어로 삭제해보겠습니다.

9BFDFBF7-4D2F-49F8-A335-D7B69DB3418E_4_5005_c.jpeg

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

강의실.PNG(1).png
3.2. branch 복구

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

1단계. git reflog로 복구 시점 확인

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

$ git reflog
$ git reflog

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

Gary 브랜치를 git branch -D Gary 명령어로 삭제 한 뒤, 복구 시켜보도록 하겠습니다.

강의실.PNG(2).png

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

강의실.PNG(3).png

2단계. git checkout으로 브랜치 복구

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

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

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

강의실.PNG

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

4. merge(합병)하기

알잘딱깔센 GitHub

알잘딱깔센 GitHub

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

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

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

$ git push origin main
$ git push origin main
알잘딱깔센 GitHub

알잘딱깔센 GitHub

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

$ git merge Gary
$ git push origin main
$ git merge Gary
$ git push origin main
알잘딱깔센 GitHub

알잘딱깔센 GitHub

5. conflict (충돌)

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

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

hello world
hello Gary
hello world
hello Gary
hello world
hello binky
hello world
hello binky

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

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

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

hello world
hello binky Gary
hello world
hello binky Gary

이후 add > commit > push 를 해주시면 됩니다.

5.1 VSC에서 conflict (충돌) 해결하기

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

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

Untitled
5.2 conflict 실습 전체 코드
  • 문제

    main branch :
        -readme 파일 'hello world'
    a branch :
        - readme 파일 'hello a' 수정
        - a폴더 > a.txt(hello1) 생성
    b branch :
        - readme 파일 'hello b' 수정
        - b폴더 > b.txt(hello2) 생성
     
    2개를 merge, 충돌 해결
    main branch :
        -readme 파일 'hello world'
    a branch :
        - readme 파일 'hello a' 수정
        - a폴더 > a.txt(hello1) 생성
    b branch :
        - readme 파일 'hello b' 수정
        - b폴더 > b.txt(hello2) 생성
     
    2개를 merge, 충돌 해결
  • 명령어

    ########## master branch ##########
    git init
    echo 'hello world' >> README.md
    git add .
    git commit -m '1'
    git branch a
    git branch b
     
    ########## a branch ##########
     
    git checkout a
    # 메모장으로 hello a로 수정 후 저장
    mkdir a
    cd a
    touch a.txt
    cd ..
    git add .
    git commit -m '2'
     
    ########## b branch ##########
     
    git checkout b
    # 메모장으로 hello b로 수정 후 저장
    mkdir b
    cd b
    touch b.txt
    cd ..
    git add .
    git commit -m '3'
     
    ########## master branch ##########
     
    git checkout master
    git merge a
    git merge b # 충돌 발생, VSC에서 해결해보세요.
    ########## master branch ##########
    git init
    echo 'hello world' >> README.md
    git add .
    git commit -m '1'
    git branch a
    git branch b
     
    ########## a branch ##########
     
    git checkout a
    # 메모장으로 hello a로 수정 후 저장
    mkdir a
    cd a
    touch a.txt
    cd ..
    git add .
    git commit -m '2'
     
    ########## b branch ##########
     
    git checkout b
    # 메모장으로 hello b로 수정 후 저장
    mkdir b
    cd b
    touch b.txt
    cd ..
    git add .
    git commit -m '3'
     
    ########## master branch ##########
     
    git checkout master
    git merge a
    git merge b # 충돌 발생, VSC에서 해결해보세요.

VSC에서 git bash 사용하는 방법

  • 디폴트로 설정하기

    Window VSC에서 Ctrl + Shift + P
    Mac VSC에서 cmd + shift p
     
    Select Default Profile 입력 후 선택
     
    Git Bash 선택
    Window VSC에서 Ctrl + Shift + P
    Mac VSC에서 cmd + shift p
     
    Select Default Profile 입력 후 선택
     
    Git Bash 선택
  • +버튼을 클릭하여 git bash로 열기 Untitled

2.4 GitHub2.6 Fork