Study Programming/Git

Git 브랜치(Branch)다루기2 - 삭제, Merge 방식

네모메모 2021. 8. 6. 23:35
반응형

 


 

브랜치 삭제 : $ git branch -d <BranchName>

- 해당 브랜치를 삭제한다.

 


 

 

특정 브랜치 생성해 작업 후 이를 다른 브랜치로 병합(=합치기=merge)해야할 때 '브랜치 병합'이 필요하다.

 

 

브랜치 병합(=merge=합치기=머지) : 
  ①  $ git checkout <병합 작업할 브랜치명> 명령 후,

  ②  $ git merge <병합 대상인 브랜치명> 명령 실행한다!

 

 - ① 다른 브랜치(B) 내용을 병합할 브랜치(A)로 이동 후 (checkout),

   ② 다른 브랜치(B)를 병합할 브랜치(A)에 합친다. (merge)

$ git checkout A 
$ git merge B

 

 - 주의) "아직 커밋하지 않은 파일이 Checkout 할 브랜치와 충돌 나면 브랜치를 변경할 수 없다."

 


 

이렇게 말해도 이해 잘 안 간다.

일단 예제를 보는 게 더 이해가 쉽다!

 

Example) 브랜치 merge, 제거 예제

상황은 아래와 같다.

- 'main' 브랜치만 존재하는 원격 저장소 프로젝트
- 프로젝트에 다음 달까지 QnA 기능개발되어야 한다 ->  'addQnA'라는 브랜치를 생성해 작업할 예정
- (QnA 기능 개발 도중) 긴급 이슈 발생해 수정이 필요 -> 'hotfix'브랜치 생성해 이슈 수정 작업할 예정

 

ⓐ 'main'브랜치만 존재하는 원격 저장소 프로젝트의 형상

- 초록색 사각형 : 원격 저장소 프로젝트 커밋사항

  원격 저장소 프로젝트에는 커밋사항은 자신의 이전 커밋사항을 가리키며 연결되어 있다.

- 'main' 브랜치(remote)  마지막 커밋사항인 'commit 1002'를 가리킨다.

   ㄴ> 브랜치 : 마지막 커밋을 가리키는 포인터 같은 것

 



ⓑ 내달까지 QnA 기능이 추가 개발되어야 해서

    원격 프로젝트의 최신 형상(commit 1002)을 로컬로  checkout으로 가져오고

    이를 바라보는 'addQnA'라는 브랜치를 생성한다.

$ git checkout -b addQnA
Switched to a new branch "addQnA"

 

 ㄴ> 브랜치를 생성 및 이동(Checkout)까지 한 번에 하려면 $ git checkout 명령에 -b 라는 옵션을 추가 

 ㄴ> 위 명령어 수행 후 로컬 저장소 형상은 아래와 같다.

 

- 'main' 브랜치(local)  Git이 자동으로 생성한 브랜치로 원격 마지막 커밋사항인 'commit 1002'를 가리킨다.

- 'addQnA' 브랜치는 지금 막 생성되어 원격 마지막 커밋사항인 'commit 1002'를 가리킨다.

- 'HEAD' 브랜치는 로컬에서 지금 작업 중인 "브랜치(branch)"를 가리키는 포인터이다.

                         $git checkout -b 명령으로 생성된 브랜치 이동하였으므로 작업 중인 'addQnA' 브랜치를 가리킨다.

 



일부 QnA 기능 개발해서 로컬에 커밋(commit 1003)한 경우

- 'addQnA' 브랜치 'HEAD' 브랜치로컬에 새로운 커밋사항을 따라 이동한다.

 

 

 


 

ⓓ 이때 긴급 수정 이슈 발생했다!!

     -> 원격의 최신 형상(commit 1002)에서 이슈 수정을 위한 'hotfix' 브랜치를 로컬에 생성하고,

          'hotfix' 브랜치에서 이슈 수정 작업을 하려고 한다

 


 

 

ⓔ 하지만 현재 내 로컬에는 개발중인 'addQnA' 브랜치 작업 사항들이 존재하므로

    이 상태로 작업하면, 'addQnA' 브랜치의 작업사항에 'hotfix' 브랜치의 버그 해결작업들이 섞일 위험이 있다;;

 

∴ 이를 방지하기 위해 'addQnA' 브랜치의 작업사항을 어딘가에 저장해두고,

'addQnA' 브랜치 작업하기 전인 'main'브랜치 형상으로 내 로컬이 변해야 한다.

 

※ 주의) 내 로컬 브랜치 변경 시, 커밋하지 않은 파일이 Checkout 할 브랜치와 충돌 날 수 있다 ※  
( Stash이나 커밋 Amend 등으로 충돌해결가능하나 아직 모르므로.......;;;;;;
일단 지금은 작업하던 것을 모두 커밋하고 main 브랜치로 옮기자!! )

 

-1)  'main'브랜치 로 내 로컬을 변경

$ git checkout main
Switched to branch 'main'

- ※ 주의) 브랜치를 이동에는 "아직 커밋하지 않은 파일이 Checkout 할 브랜치와 충돌 나면 브랜치를 변경할 수 없음"을 주의하여
           로컬의 워킹 디렉토리를 정리하는 것이 좋다. 
- 'main' 브랜치(local)  'addQnA' 브랜치의 작업사항이 없는 이전 형상으므로 새로운 문제에 집중할 수 있는 환경이 만들어진다. 
 





ⓕ 이슈 수정을 위한 'hotfix'브랜치 생성 및 이동(checkout)한다.

$ git checkout -b hotfix
Switched to a new branch 'hotfix'

-이제 'hotfix' 브랜치 로컬에 새로운 커밋사항을 따라 이동한다.

 

 




ⓕ 긴급 수정 이슈 수정하여 로컬에서 커밋(commit 1004)했다.

$ git commit -a -m 'fixed the broken email address'

 

- 로컬의 작업 브랜치인 'hotfix' 브랜치로컬의 새로운 커밋사항(commit1004)를 따라 이동한다.
- 'HEAD' 브랜치는 지금 작업 중인 브랜치인  'hotfix' 브랜치를 가리킨다.

 



ⓖ 긴급 이슈 수정 작업 완료 후 'hotfix' 브랜치main 브랜치에 합쳐야 한다.

- 운영 환경에 적용하려면 문제를 제대로 고쳤는지 테스트하고 최종적으로 운영환경에 배포하기 위해서
   hotfix 브랜치를 master 브랜치에 합쳐야 한다.

- $ git merge 명령으로 브랜치를 합칠(=merge=병합) 수 있다.

 

 

$ git checkout main
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

- 명령어 실행 결과 메시지에서 'fast-forward' 확인!!!
- 'hotfix' 브랜치가 가리키는 (commit 1004) 커밋이 (commit 1002) 커밋에서 갈라진 브랜치이기 때문에 merge하면
  'main' 브랜치 포인터는 그저 최신 커밋으로 이동한다. 이러한 Merge 방식을 'Fast forward' 라고 부른다. 

 

 

['Fast forward' 방식]

 : A 브랜치에서 다른 브랜치 B 를 Merge 할 때  B 브랜치가 A 브랜치 이후의 커밋을 가리키고 있으면(A의 커밋이 B의 조상),
    B 브랜치와 동일한 커밋을 가리키도록 A브랜치가 가리키는 곳만 이동하는 Merge 방식.

- Merge 방식 중 하나

 

+) 그림 22. Merge 후 hotfix 같은 것을 가리키는 master 브랜치

 

 


 


ⓗ 이제 더 이상 필요없는 'hotfix' 브랜치는 삭제한다.

$ git branch -d hotfix
Deleted branch hotfix (3a0874c)


  


 


ⓘ 다시 작업하던 'addQnA' 브랜치로 되돌아가서 개발하고 커밋을 해보자.

 

ⓘ-1)  'addQnA' 브랜치로 이동(checkout)

$ git checkout addQnA
Switched to branch "addQnA"

 

ⓘ-2)'addQnA' 브랜치에서 새 작업사항 커밋 (commit1005)

$ git commit -a -m 'finished the new footer [addQnA]'
[addQnA ad82d7a] finished the new footer [addQnA]
1 file changed, 1 insertion(+)



위에서 이슈 수정 작업('hotfix' 브랜치)이 addQnA 브랜치에 영향을 끼치지 않는다

 

 


이후, #1 or #2 방식으로 Merge 진행 가능하다.


#1) main 브랜치addQnA 브랜치에 병합(Merge)

   - $ git merge main 명령으로 main 브랜치를 addQnA 브랜치에 Merge 하면

      addQnA 브랜치hotfix 이슈 수정 사항이 적용된다. 

 


#2) addQnA 브랜치 개발 완료 후 main 브랜치 병합(Merge)

   - addQnA 브랜치main 브랜치에 Merge 할 수 있는 수준이 될 때까지 기다렸다가 

      Merge 하면 hotfix addQnA 브랜치가 합쳐진다. 
   - 그림 24. 커밋 3개를 Merge

 

$ git checkout main
Switched to branch 'main'
$ git merge addQnA
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

 

ㄴ> "현재 브랜치가 가리키는 커밋이 Merge 할 브랜치의 조상이 아니므로" Git은 'Fast-forward’로 Merge 하지 않는다. 

        cf) hotfix 를 Merge 했을 때 메시지
ㄴ> 이 경우에는 Git은 각 브랜치가 가리키는 커밋 두 개와 공통 조상 하나를 사용하여 '3-way Merge'를 한다.

 

 


['3-way Merge' 방식]

 : A 브랜치에서 다른 브랜치 B 를 Merge 할 때  B 브랜치가 A 브랜치 이후의 커밋이 아니면 (A의 커밋이 B의 조상이 아님!)
    (단순히 브랜치 포인터를 최신 커밋으로 옮기는 게 아니라) 3-way Merge 결과를 별도의 커밋으로 만들고 나서
    A 브랜치가 그 별도의 커밋을 가리키도록 이동시키는 Merge 방식.


- 이런 별도의 커밋[Merge 커밋]이라고 한다.

-Merge 방식 중 하나

- (그림 24. 커밋 3개를 Merge -> 그림 25. Merge 커밋)

 


[Merge 커밋]

 : (사용자 요청에 의한 커밋이 아닌) merge작업 중 브랜치 포인터가 이동('Fast-forward' Merge)할 수 없는 경우,
   Git이 두 브랜치를 merge하고 이를 커밋한 것을 말한다.

  - 이전 커밋(='parent'=부모 커밋)이 여러개이다.

 


 

ⓚ addQnA 브랜치를 master에 Merge 후 addQnA 브랜치를 삭제하고 이슈의 상태를 처리 완료로 표시

$ git branch -d addQnA





 

 


 

END!

 

 


스터디 도움 참조 블로그 (References)

- 3.2 Git 브랜치 
https://git-scm.com/book/ko/v2/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%99%80-Merge-%EC%9D%98-%EA%B8%B0%EC%B4%88

- 브랜치 명령어
https://backlog.com/git-tutorial/kr/reference/branch.html


- git--distributed-even-if-your-workflow-isnt (Pro Git Book)
https://git-scm.com/book/en/v2

 

 

 

반응형