오픈소스SW

오픈소스SW_Chpater08_병합과 충돌

강용민 2022. 10. 24. 12:56

1. 병합

 브랜치를 생성하는 목적은 원본 코드에 영향을 주지 않고 분리하여 개발하기 위함이다. 독립된 브랜치에서 개발 작업이 끝나면 다시 원본 브랜치에 작업한 결과를 반영해야한다. 병합은 분리된 브랜치를 한 브랜치로 합치는 작업이다.

 깃의 병합은 브랜치를 기준으로 실행한다.병합할 때는 상대적인 기준을 판별하는 알고리즘들이 존재하며 Fast-Forward 병합과 3-way 병합 방식을 제공한다.

git merge 병합할 브랜치명
  • Fast-Forward
    • 깃의 가장 간단한 브랜치 병합 방식으로 순차적 커밋에 맞추어 병합을 처리하는 방법이다. 혼자 개발할 때 주로 사용한다.
    • 작업한 브랜치를 원본 브랜치에 병합할 때 작업한 브랜치의 시작 커밋을 원본 브랜치 이후에 커밋으로 가리킨다.
    • 브랜치를 병합하려면 기준과 대상이 필요한데, 기준은 체크아웃 된 현재 브랜치이다.
  • 3-Way
    • 공통 조상 커밋을 포함하는 브랜치와 새로운 두 개의 브랜치, 이렇게 3개를 하나로 병합하는 방식이다. 여러 개발자와 협업으로 작업하는 경우 대부분 3-way 병합을 사용한다.
      • 공통 조상 커밋 : 두 브랜치를 병합하기위한 분할 기준인 공통 커밋
    • 병합을 성공적으로 완료한 후에는 새로운 커밋을 추가로 하나 생성한다.

 

2. 삭제

병합된 브랜치의 커밋은 모두 원본 브랜치에 적용되므로 중복되는 커밋을 가지는 별도의 브랜치를 유지할 필요는 없으므로 불필요한 브랜치는 삭제해야 한다.

git branch -d 브랜치명

 

3.충돌

파일에서 동일한 위치에 두 명 이상이 서로 다르게 수정했다면 충돌이 발생하기도 한다. 그때는 개발자가 수동으로 수정을 해줘야 한다.

그럼 어떤 충돌 상태인지 어떻게 알아볼까? git status로 알아볼 수 있다. Unmerged paths라 적혀있고 그 안에 충돌지점이 적혀있다.

충돌 후 현재 문제가 된 코드를 보면 다음 그림처럼 되어있다.

직접 충돌을 해결하면 파일은 modified 상태가 되며 다시 add를 해줘야한다.

 

브랜치 병합 여부 확인

다수의 브랜치가 있을 때는 어느 브랜치가 병합을 완료한 것인지 알기 어렵기에 다음 명령어를 통해 확인할 수 있다.

git branch --merged
  • --no-merged : 병합하지 않은 브랜치 확인

병합한 브랜치는 별표(*) 기호로 표시되어 있다.

 

4. 리베이스

브랜치는 커밋 하나를 기준으로 새로운 작업을 진행할 수 있는 분리된 작업 경로를 의미하기도 한다. 새로운 브랜치가 파생되는 커밋을 베이스(base)라 하며, 병합 시에는 공통 조상 커밋이라 부른다.

깃은 이 베이스 위치를 변경할 수 있다. 브랜치의 베이스를 변경하는 이유는 여러 갈래로 갈라져있는 베이스 분기점을 하나의 기차길처럼 만들어 진행 사항을 좀 더 쉽게 파악하기 위해서이다.

git rebase 브랜치
  • --continue : 계속진행
  • -i : 여러 커밋을 하나의 커밋으로 묶을 수 있다.

리베이스에서 브랜치 커밋을 결합하는 순서는 다음과 같다.

  • 공통 조상 커밋을 찾음
  • 베이스 커밋을 변경
    • 두 브랜치의 커밋 위치를 바꿈(커밋 2 -> 커밋 6)
  • 파생된 브랜치(브랜치A)의 diff(변경 내용)를 임시 공간에 잠시 보관함
  • master 브랜치의 커밋1 -> 커밋2 -> 커밋-5 -> 커밋6까지 진행함.
  • 결국 새로운 베이스 기준점을 기반으로 한 브랜치에서 커밋3 -> 커밋4를 커밋6에서 연장하여 수정 재배치함

 

리베이스 vs 병합

병합은 파생된 두 브랜치를 하나로 합치는 과정이다. 병합하려면 두 브랜치의 공통 조상 커밋을 먼저 찾고 3-way방식으로 병합하는 브랜치를 순차적으로 커밋을 비교하면서 마지막 최종 커밋을 생성한다.

 리베이스는 두 브랜치를 서로 비교하지 않고 순차적으로 커밋 병합을 시도한다. 그래서 파생된 커밋의 HEAD가 병합 후 가장 최신의 HEAD로 변경된다.

 

주의할 점

리베이스는 실행 결과로 커밋 위치와 해시 값을 변경한다. 그래서 저장소를 외부에 공개했다면 공개된 순간부터 커밋은 리베이스를 사용하지 않는 것이 원칙이다. 리베이스는 외부로 코드를 푸시하거나 공개하기 전에 로컬에서만 실행하는 것이 좋다. 외부에 공개된 커밋을 리베이스하면 커밋 위치와 해시 값이 변경되어 혼란스럽기 때문이다.

 

문제

병합 방식은 두가지가 있다. 무엇이 있으며 각각의 특징은 무엇인가?

Fast-Forward방식과 3-way 방식이 있다. Fast-Forward는 순차적으로 커밋했을 때 사용되며, 작업한 브랜치의 시작 커밋이 원본 브랜치 이후 커밋을 가리킨다. 반면에 3-way방식은 브랜치끼리의 모양이 갈라지는 형태로 나뉠 때 공통 조상 커밋

을 기준으로 3개의 브랜치를 하나로 병합한다.이렇게 생성된 커밋을 병합 커밋이라한다.

 

브랜치 삭제 명령어는 무엇인가?

git branch -d 브랜치명

 

어느 브랜치와 병합했는지 확인하려면 어떤 명령어를 사용하는가?

git branch --merged

 

리베이스는 어떤 명령어를 사용하는가

git rebase 병합할 브랜치명

 

리베이스와 병합의 차이는 무엇인가?

병합은 파생된 두 브랜치를 하나로 합치는 과정으로 병합하는 두 브랜치는 순차적으로 커밋을 비교하면서 마지막 최종 커밋을 생성하는 것에 반해 리베이스는 두 브랜치를 서로 비교하지 않고 순차적으로 커밋 병합을 시도하며 병합 커밋이 없다.

또 병합은 현재의 기준 브랜치에서 다른 브랜치를 읽어와서 결합하는 반면에 리베이스는 현재의 기준 브랜치가 다른 브랜치에 병합되는 형태이다.

 

리베이스 시 주의할 점은 무엇인가?

리베이스는 실행 결과로 커밋 위치와 해시 값을 변경하기에 로컬에서만 실행하는 것이 좋다.