0. Introduction


1. 여러 branch (다른 차원) 만들어보기

아래의 모든 것을 하나의 프로젝트 폴더에서 진행할 수 있도록 여러 branch를 만든다.

image

언제 branch를 여러 개 만들어서 작업을 할까??

  • 프로젝트를 하나 이상의 모습으로 관리해야할 때

    • 예) 실배포용, 테스트 서버용, 새로운 시도용
  • 여러 작업들이 각각 독립되어 진행될 때

    • 예) 신기능 1, 신기능 2, 코드개선, 긴습 수정 …
    • 각각의 차원에서 작업한 뒤, 확정된 것을 메인 차원에 통합한다.

1.1 브랜치 생성 / 이동 / 삭제하기 / 이름 바꾸기

  • branch 생성: add-coach란 이름의 브랜치 생성

    • git branch add-coach
  • branch 목록 확인

    • git branch
    • *은 현재 branch를 의미한다.
> $ git branch add-coach
> $ git branch
  add-coach
* main
  • 생성된 branch로 이동

    • git switch add-coach
    • *add-coach로 옮겨진 걸 알 수 있다.
    • checkut 명령어가 Git 2.23버전부터 switchrestore로 분리되었다.
> $ git switch add-coach
Switched to branch 'add-coach'

> $ git branch
* add-coach
  main
  • 💡 branch 생성과 동시에 이동하기

    • git swtich -c new-teams
    • 기존의 git checkout -b (새 브랜치명)이 이를 의미한다.
> $ git switch -c new-teams
Switched to a new branch 'new-teams'

> $ git branch
  add-coach
* main
  new-teams
  • 브랜치 삭제하기

    • git branch -d (삭제할 브랜치명)
    • to-delete란 branch 만들고, 삭제해보기
  • 브랜치 이름 바꾸기

    • git branch -m (기존 브랜치명) (새 브랜치명)
> $ git branch
  add-coach
* main
  new-teams
  to-delete

> $ git branch -m to-delete to-eraser

> $ git branch
  add-coach
* main
  new-teams
  to-eraser

> $ git branch -m to-eraser to-delete

> $ git branch -d to-delete
Deleted branch to-delete (was 1589712).

> $ git branch
  add-coach
* main
  new-teams
  • 💡 브랜치 강제 삭제

    • 지워질 브랜치에만 있는 내용의 커밋이 있을 경우, 다른 브랜치로 가져오지 않은 내용이 있는 브랜치를 지울 때는 -d 대신 -D (대문자)로 강제 삭제해야 한다.

1.2 각각의 브랜치에서 서로 다른 작업해보기

총 3개의 branch: main, add-coach, new-teams branch에서 작업한다.

각 작업을 실행할 때, git add를 실행한 후 git commit -m'()'을 해야 반영된다.

Chapter 02에서 알아봤듯이 모두 다 tracked file일 때, git commit -am'(commit message)' 로 한 번에 할 수 있다.

1.2.1 main branch

  1. Leopards의 membersOlivia 추가

    • 커밋 메시지: Add Olivia to Leopards
  2. Panthers의 membersFreddie 추가

    • 커밋 메시지: Add Freddie to Panthers

1.2.2 add-coach branch

  1. Tigers의 매니저 정보 아래 coach: Grace 추가

    • 커밋 메시지: Add Coach Grace to Tigers
  2. Leopards의 매니저 정보 아래 coach: Oscar 추가

    • 커밋 메시지: Add Coach Oscar to Leopards
  3. Panthers의 매니저 정보 아래 coach: Teddy 추가

    • 커밋 메시지: Add Coach Teddy to Panthers

1.2.3 new-teams branch

  1. pumas.yaml 추가

    • 커밋 메세지: Add team Pumas
  2. jaguars.yaml 추가

    • 커밋 메세지: Add team Jaguars

1.3 결과 살펴보기

git log로도 볼 수 있지만 git log로 볼 경우에는 현재 branch 와 갈라지기 전 main일 때의 log만 볼 수 있다.

별표는 하나의 줄기다.

$ git log --all --decorate --oneline --graph
* 672d65f (HEAD -> new-teams) Add team Jaguars
* af9742d Add team Pumas
| * 2641114 (add-coach) Add Coach Teddy to Panthers
| * e22aa3c Add Coach Oscar to Leopards
| * f91d19a Add Coach Grace to Tigers
|/
| * 7618a7e (main) Add Freddle to Panthers
| * a9fe922 Add Olivia to Leopards
|/
* 1589712 (to-eraser) replace cheetas with Panthers
* f86046e Add team Cheetas
* 679d1f1 add George to tigers
* 3183106 Replace Lions with Leopards
* ed807a6 first commit

하지만 이런 흐름을 볼 때는 실무에서는 CLI보다 source tree로 본다.

source tree로 보면 다음과 같다.

image


2. branch를 합치는 두 가지 방법

branch를 합치는 실습을 해보기 전에, 위 실습과정을 이미지로 보자면 다음과 같다.

주요 branch는 main branch다.

그리고 양 옆에 add-coach branch, new-teams branch에서 실험적인 시도를 하고 있다.

image

그리고 이 두 branch를 아래 이미지처럼 main branch로 합칠려고 한다.

image

이를 위해서 2가지 방법으로 진행할 것이다.

merge vs rebase

  • merge: 두 브랜치를 한 커밋에 이어붙이는 방식으로, 두 branch의 끝 가지를 이어붙힌다.

    • 브랜치 사용 내역을 남길 필요가 있을 때, 적합한 방식
    • mainadd-coach branch를 합칠 방식

image

  • rebase: 브랜치를 다른 브랜치에 이어붙이는 방식으로, 곁가지들을 싹 다 잘라다가 몸통 줄기에 이어 붙여서 히스토리를 한 줄로 유지가능하다.

    • 한 줄로 깔끔히 정리된 내역을 유지하기 원할 때 적합하다.
    • 이미 팀원과 공유된 커밋들에 대해서는 사용하지 않는 것이 좋다. 즉, 있던 거를 없애다가 딴 데 이어붙이는 거인 만큼 같이 일하는 도중에 이러면 문제가 발생할 수 있다.
    • mainnew-teams branch를 합칠 방식

image

❗ 이 두 가지 중 무엇을 사용하냐는 프로젝트의 성격에 달려있다. 브랜치의 사용 내역들을 남겨둘 필요가 있으면 Merge를, 그보다는 히스토리를 깔끔하게 만드는게 중요하면 Rebase를 사용한다.

2.1 Merge로 합치기

  1. main branch로 먼저 이동
  2. git merge add-coach 명령어로 병합
$ git merge add-coach

❗ 위 과정에서 충돌이 났을 경우, 3. 충돌해결하기를 참고한다.

  • 병합된 브랜치는 아래 명령어로 삭제한다.
    • 삭제 전 소스트리에서 add-coach 위치 확인한다.
git branch -d add-coach

💡 Rebase와의 차이점: mergereset으로 되돌리기 가능하다.

  • merge 도 하나의 커밋이기 때문에, merge 하기 전 해당 브랜치의 마지막 시점으로 되돌리는 게 가능하다.

Merge한 결과는 다음 이미지와 같다.

image

2.2 Rebase로 합치기

  • new-teams 브랜치를 main 브랜치로 rebase

💡 Merge와의 차이점: merge와는 반대로 new-teams로 이동하여 아래 명령어로 병합한다.

$ git rebase main
  • 소스트리에서 상태를 확인하면 아래 이미지처럼 main 브랜치가 뒤쳐져있다.

image

  • main 브랜치로 이동 후, 아래 명령어로 new-teams의 시점으로 앞으로 이동한다.
$ git merge new-teams

위 이미지와 달리 앞으로 이동된 걸 알 수 있다.

image

그리고 new-teams 브랜치를 삭제한다.


3. 충돌 해결하기

3.1 충돌 상황 만들기

  1. conflict-1, conflict-2 브랜치 생성

  2. main branch

  • Tigers의 managerKenneth로 변경
  • Leopards의 coachNicholas로 변경
  • Panthers의 coachShirley로 변경
  • 커밋 메시지: Edit Tigers, Leopards, Panthers
  1. conflict-1 branch
  • Tigers의 managerDeborah로 변경
  • 커밋 메시지: Edit Tigers
  1. conflict-2 branch
  • Leopards의 coachMelissa로 변경
  • 커밋 메시지: Edit Leopards
  1. conflict-2 branch
  • Panthers의 coachRaymond로 변경
  • 커밋 메시지: Edit Panthers

3.2 merge 충돌 해결하기

  1. main 브랜치에서 git merge conflict-1 로 병합을 시도하기

    • 그러면 아래와 같은 충돌이 발생한다.
    $ git merge conflict-1
    Auto-merging tigers.yaml
    CONFLICT (content): Merge conflict in tigers.yaml
    Automatic merge failed; fix conflicts and then commit the result.
    
    • 그러면 VSC에서 해당 파일 옆에 !로 뜬다.
    • 해당 파일을 클릭하면 Accept Current Change, Accept Incoming Changes 등을 선택라고 한다.
    • 이 때, 해당 파일은 일반 폴더에서 더블 클릭하여 열면 단순 text로 나타난다. 이를 VSC에서 보기 좋게 표현한 것이다.
    • 충돌되는 부분만 찾고 싶다면 VSC 검색에서 <<<<< 을 입력하여 찾을 수 있다.
  2. Accept Current Change, Accept Incoming Changes 등을 선택하여, 충돌 부분을 수정한 뒤, git add. -> git commit으로 병합을 완료한다.

    • 하지만, 당장 충돌 해결이 어려울 경우, 아래 명령어로 merge를 중단한다.
    git merge --abort
    

3.3 rebase 충돌 해결하기

  1. conflict-2에서 git rebase main으로 rebase 시도하면 충돌 발생한다.

    • 오류 메시지와 git status 확인한다.
     $ git rebase main
     Auto-merging leopards.yaml
     CONFLICT (content): Merge conflict in leopards.yaml
     error: could not apply f8bddeb... Edit Leopards
     hint: Resolve all conflicts manually, mark them as resolved with
     hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
     hint: You can instead skip this commit: run "git rebase --skip".
     hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
     Could not apply f8bddeb... Edit Leopards
    
    
     $ git status
     interactive rebase in progress; onto 528ecc7
     ...
     Unmerged paths:
     (use "git restore --staged <file>..." to unstage)
     (use "git add <file>..." to mark resolution)
         both modified:   leopards.yaml
    
    • VS Code에서 해당 부분을 확인한다.
  2. Accept Current Change, Accept Incoming Changes 등을 선택하여, 충돌 부분을 수정한 뒤, git add. -> git commit으로 병합을 완료한다.

    • 하지만, 당장 충돌 해결이 어려울 경우, 아래 명령어로 merge를 중단한다.
    git rebase --abort
    
    • 해결 가능 시,

      • 충돌 부분을 수정한 뒤 git add .를 입력한다.
      • 아래 명령어를 입력한다.
      git rebase --continue
      
      • 충돌이 모두 해결될 때까지 반복한다.
  3. main에서 git merge conflict-2로 마무리한다.

    • main을 앞으로 이동
  4. conflict-1conflict-2를 삭제한다.

    • 다 사용한 branch는 바로 바로 지워서 혼란스럽게 만들지 말자.

Reference