본문 바로가기

기타

Git (3) - merge와 branch

지금까지 배운 내용으로 개발자들과 원격 repo에 있는 소스를 공유할 수 있다.

그러나, 동시에 같은 소스파일을 수정하여 push하면 어떻게 될까?

 

충돌(conflict)이 발생하게 된다.

 

이미지 출처 : 스파르타 코딩클럽

 

위와 같은 상황을 대비하기 위해서, 하기의 작업 방식을 지킬 필요가 있다.

 

 

Git을 이용한 협업 과정

1. 누가 이 작업을 진행할 것인지 정한다. (issue 할당)

2. 각자 맡은 것에 대해 작업한다. (branch)

3. 각자 작업을 프로젝트에 합칠 수 있게 공유한다.

4. 작업한 내용을 리뷰하고 최종적으로 프로젝트에 반영한다. (merge)

 

 


Issue 할당

issue란?

프로젝트에서 해결해야하는 문제. (버그, 기능 추가 등의 프로젝트 개선 제안, 문제 해결을 위한 작업단위)

 

다양한 이슈 추적 툴(Issue Tracking Tool)들을 이용하여 이슈를 할당하고, 업데이트할 수 있다.

 

Github의 경우에는 프로젝트 별로 issue를 관리하는 페이지가 존재한다.

 

 

Issue 생성

 

New Issue를 눌러, 새로운 이슈를 생성할 수 있다.

 

 

제목과 상세 내용을 적고, 이슈를 작업할 사람을 Assignees에 지정한다.

해당 이슈가 어떤 것인지 Labels에 등록하여 한 눈에 파악할 수 있도록 하자.

 

 

 

생성을 완료하면 위처럼 이슈 번호가 할당된다. 후에 작업 후 팀원들과 소통할 때 이 번호를 정보로 사용할 것이다. (이슈 번호는 #1 부터 시작한다.)

 

 

 

Issue 완료하기

 

 

화면 하단의 'Close Issue' 를 누르면 이슈가 종료된다. 종료시 이유를 함께 적어주면 History 파악에 용이하다.

 

 

Issue ReOpen

 

 

이슈를 종료하였더라도, 'Reopen' 버튼을 눌러 다시 이슈를 열어줄 수 있다.

 

 

Comment에 이슈 정보 사용하기

issue와 관련된 commit 진행 시, 코멘트에 해당 이슈에 대한 정보를 기입해주면 issue 탭에서 내역 확인이 가능하다.

 

 

 


Branch

이슈가 할당되면, 각자의 공간에서 작업을 진행하게 된다.

Branch는 마치 나뭇가지가 뻗어나오듯, 각자 작업할 수 있는 공간을 만들기 위해 사용한다.

 

출처 : 스파르타 코딩클럽

 

위는 Branch 사용 예시이다. 각자 부여받은 issue에 해당하는 작업을 진행한다.

김칫국은 김칫국 branch를 만들어서 관리하고, 김치찜은 김치찜 branch를 만들어 관련 작업을 진행한다.

이후, merge를 진행하면 하나의 프로젝트로 합칠 수 있다.

 

 

 

Branch 생성

 

앞서 올려둔 김치찌개 레시피를 두부김치찌개 레시피로 변경한다고 가정해보자.

 

먼저, 이슈를 생성하고 할당해주었다.

 

소스트리에서 마지막 commit을 우클릭하여 브랜치를 선택해준다.

 

 

새 브랜치 생성 창이다.

브랜치 명은 보통 feature/이슈번호_브랜치명 으로 명명한다.

 

 

브랜치가 생성된 것을 확인할 수 있다.

 

브랜치 옆에 O모양은 체크아웃된 브랜치임을 나타내는 것이다.

여기서 체크아웃이란 현재 작업하는 브랜치를 선택해주는 것을 말한다.

 

앞으로 하는 commit은 feature/2_jjigae 브랜치에만 반영될 것이다.

 

이외의 브랜치들에 대해 설명하자면, 다음과 같다.

origin/main - origin(현재 연결된 원격 repo)의 main(기본 .브랜치)브랜치

main - 로컬 repo의 main 브랜치

 

현재 각자 브랜치들의 상황을 정리해보면,

main 브랜치의 마지막 commit을 기점으로 feature/2_jjigae 브랜치가 갈라져 나온 것이다.

main 브랜치의 마지막 commit은 그대로 유지되고 있는 상태이다.

 

 

이어서 두부 김치찌개 요리법을 추가해주고, commit을 진행하였다.

feature/2_jjigae 브랜치에 정상적으로 commit 되었다.

 

 

Branch 삭제

 

test용으로 브랜치를 하나 생성해주었다.

브랜치를 생성하면 자동으로 해당 브런치가 체크아웃 되는데, 체크아웃된 브랜치는 삭제할 수 없으므로 해제해준다.

 

 

소스트리 왼쪽 상단에서 브랜치 명을 확인할 수 있다. 삭제할 브런치를 선택하여 삭제해주면 된다.

 

 


Merge

Merge(병합)은 브랜치를 다른 브랜치에 합치는 것이다.

특정 브랜치의 commit들을 다른 브랜치의 commit내역에 모두 반영하는 것이다.

 

이미지 출처 : 스파르타 코딩 클럽

 

실제 프로젝트 진행 시, 작업 내역을 모두 합칠 기준이 되는 브랜치를 정해두고 작업한다.

이때, commit하고 작업하는 방법을 통틀어 flow(흐름) 라고 한다.

 

웹 프로젝트 개발의 경우 github-flow를 많이 사용하므로, 해당 flow로 작업을 진행하였다.

 

 

main 브랜치에 Merge 하기

 

commit을 반영시킬 main 브랜치로 체크아웃 한다.

화면 상단 병합 버튼을 누르면 현재 체크아웃된 브랜치에 병합할 커밋을 선택할 수 있다.

 

 

옵션 선택이 가능한데, 아직까지는 정확한 의미는 모르겠다. 가이드라인을 따라서 옵션을 선택해주었다.

 

병합 완료!!

 

병합이 완료되면, 개별 생성하여 사용했던 브랜치를 삭제해주면 된다.

 

 

 

Merge conflict 해결하기

confilict는 하나의 파일을 여러 브랜치에서 수정하고, 하나의 브랜치에 merge하려고 할때 발생한다.

 

conflict를 고의로 발생시키고, 이를 해결하는 과정을 실습하고자 하였다.

 

 

위 화면까지의 과정을 간략히 설명하자면,

1. 마지막 main 브랜치로부터 feature/stock , feature/jjigae-rtan 브랜치를 생성

2. 각자의 브랜치에서 jjigae.txt 파일을 수정한 뒤에 commit을 진행

3. feature/stock 브랜치를 main 브랜치에 merge

 

일단, feature/stock 은 merge하려는 commit 중 같은 파일을 수정한 내역이 없기 때문에 정상적으로 진행되었다.

 

이제 feature/jjigae-rtan 브랜치의 병합을 시도하면,

 

 

충돌이 발생했다는 메세지를 확인할 수 있다.

 

이후에 History를 확인하면, 커밋하지 않은 변경사항이 새로 생긴 것을 확인할 수 있는데,

이는 충돌이 난 내용을 자동으로 파일에 적어주어 발생한 내역이다.

 

충돌에 대하여 새롭게 추가된 내용을 확인할 수 있다.

 

<<<<<<< 에서 >>>>>>>>> 까지가 충돌이 발생한 부분이다.

아래와 같은 형식으로 나타낸다.

<<<<<<< HEAD 부분은 main 브랜치의 파일 내용을 보여준다.

======를 기준으로 >>>>>> 는 feature/jjigae_rtan의 파일 내용을 보여준다.

 

충돌을 해결하기 위해서는 <<<<< HEAD 와 >>>>>>> feature/jjigae_rtan 이 파일에서 사라지면 충돌이 해결 되었다고 판단한다.

 

파일을 수정한 후에, 소스트리에 들어가서 확인해보면 자동으로 충돌에 대한 커밋 메세지가 추가된 것을 확인할 수 있다.

 

 

이후 commit을 시도하면 정상적으로 작업이 완료된다.

 

merge가 완료되었다!

 

지금까지의 과정을 정리하면 다음과 같다.

 

이미지 출처 : 스파르타 코딩클럽

 

 


원격 repo와 Branch

이전에, 로컬 repo를 원격 repo에 Tracking 해주면 연결이 완료된다는 것을 배웠다.

branch의 개념까지 상세히 들어가자면, 사실 이는 로컬 repo의 브랜치와 원격 repo의 브랜치가 연결된 것이다.

 

 

이미지 출처 : 스파르타 코딩클럽

 

pull과 push는 특정 branch에 있는 commit을 이곳과 연결되어 있는 branch에 가져오는 것이다.

해당 내용은 현재까지 진행했던 실습에 대한 History에서 확인할 수 있다.

 

 

History를 확인해보면, 로컬 repo main의 commit과 원격 repo main의 commit이 다른 것을 확인할 수 있다.

 

main(로컬 repo)의 마지막 commit은 Merge branch 'feature/jjigae_rtan' 이고,

origin/main(원격 repo)의 마지막 commit은 김치찌개 육수 요리법 추가 #1 이다.

 

로컬 repo의 내용을 원격 repo에 push하면 내용이 반영된 것을 github에서 확인할 수 있다.

 

 

정리해보면, Push는 로컬 repo-  특정 branch의 commit을 원격 repo에 밀어넣는 것이며,

Pull은 원격 repo - 특정 branch의 commit을 로컬 repo로 받아오는 것이다.

 

또한, main에서 main으로만 가능한 것이 아니라, 특정 branch를 지정하여 옮겨줄 수 있다.