여러분은 Git과 친하신가요?
개발자라면 피할 수 없는 존재가 바로 Git일텐데요.
하지만 전 Git 하수... Git을 매일 사용하지만 패키징 기간이 오면 머지할 생각에 걱정부터 앞서는 주니어 개발자입니다.
따라서 오늘은 저희 팀에서 사용하는 upstream을 활용하는 Git 머지 방법에 대해 정리해보려고 합니다.
# Git-Flow 전략
일단 저희 팀은 기본적으로 Git-Flow 전략을 채택하고 있습니다.
항상 유지되는 master, develop 브랜치와
일시적으로 생성되는 feature, release, hotfix 브랜치로 구성되는 branch 전략입니다.
master (or main)
배포된 최종 버전이 존재하는 브랜치입니다.
언제든지 제품으로 바로 사용할 수 있는 상태여야 합니다. 따라서 제일 안정적인 상태라고 할 수 있겠네요.
develop
개발자들이 작업하는 기본 브랜치입니다. develop을 기준으로 feature 브랜치를 생성하게 됩니다.
feature/*
새로운 기능을 개발할 때 사용하는 브랜치입니다. 보통 feature/이슈번호 및 제목 이런 식으로 브랜치를 생성합니다.
개발이 완료되면 develop에 머지합니다.
release/*
배포 전 안정화 작업을 위한 브랜치 입니다.
저희는 주로 패키징 시 develop에서 release/버전명 으로 브랜치를 생성하여 사용하고 있습니다.
패키징이 완료되면 develop, master에 머지합니다.
hotfix/*
배포 후 긴급 수정 사항이 발생한 경우 사용하는 브랜치입니다.
master에서 생성하여 작업 후 바로 develop,master에 반영하게 됩니다.
# upstream을 활용하는 Git 머지 방법
패키징을 하게 되면 다음 버전의 제품 출시를 위해서 그동안 기능 개발한 코드들을 develop에 머지하게 되는데요
문제는 반영되어야 하는 기능들이 한두개가 아니라는 것이죠.
따라서 피하고 싶은 merge conflict가 와장창 발생하게 됩니다.
o---o---o--o---o---o---o (develop)
\ \
o---o---o-----------------M (feature, merge commit)
이럴 때 upstream을 활용해서 머지 충돌 부담을 줄일 수 있습니다.
upstream 을 활용해서 merge 하는 방식의 이점 :
- feature 브랜치가 오래되어 소스코드 최신화가 필요한 경우 upstream 사용
- develop 소스의 복제본을 가져와서 개발중인 feature branch와 merge 하여 최신화
- develop에 영향을 주지 않고 합칠 수 있음
1️⃣ upstream 원격 저장소 추가 (이미 존재한다면 생략가능)
- git remote -v : 현재 원격 저장소 확인 (명령어 결과에 origin만 있다면 upstream을 추가해야함)
- git remote add upstream <원본 저장소 URL> : upstream 원격 저장소 추가
2️⃣ feature 브랜치 최신화
feature 브랜치를 develop의 최신 상태를 이용해서 최신화합니다.
병합하는 과정에서 충돌이 발생할 수 있습니다.
- git fetch upstream : upstream 저장소 fetch 작업
- git merge upstream/develop feature/#### : upstream의 develop 소스를 작업중인 feature 브랜치에 merge
3️⃣ develop 브랜치에 feature 브랜치 머지
- git checkout develop : develop 브랜치 이동
- git merge feature/#### : feature 브랜치를 develop에 merge
# upstream 을 굳이 사용해야하나?
upstream을 사용하면 뭐가 다를까요?
feature 브랜치를 최신화 하지 않고 develop에 feature 브랜치를 머지한다면, 머지할 때 충돌을 해결해야 하죠.
하지만 upstream을 사용해서 최신 develop 기준으로 feature 브랜치를 업데이트를 하면 머지 충돌을 미리 해결할 수 있습니다.
그리고 실제로 develop에 머지할 때 충돌 가능성이 낮아지므로 develop을 안정적으로 유지할 수 있습니다.
# 실제로 사용해보기
직접 사용하면서 origin/develop으로 바로 머지하는 방식과 비교해보겠습니다.
간단하게 README.md 파일을 수정해볼게요.
// A가 작성할 코드
## origin/develop 으로 pull 없이 머지하기
### 1. feature.first 커밋
// B가 작성할 코드
### 2. feature/second 커밋
# case 1. origin/develop 을 이용한 merge
1) A가 develop브랜치에서 feature/first를 머지
-> 충돌 발생하지 않음
2) B가 머지 전 fetch를 해서 develop을 최신화 한다(pull)
그 후 develop브랜치에서 feature/second를 머지했습니다.
-> 충돌 발생
머지 충돌이 발생한 파일을 열어보면 어디가 문제가 되는지 확인할 수 있습니다.
<<<<<<< HEAD
// 충돌이 일어난 부분 표시
>>>>>>>
Git에서 친절하게 ======= 를 기준으로 코드를 나눠서 표시를 해줍니다.
이 부분을 내가 반영하고 싶은 모습으로 수정해줍니다.
그리고 develop 브랜치에서 커밋, 푸시를 해줍니다.
그럼 아래와 같은 모습을 볼 수 있습니다.
그런데 말입니다?
만약 B가 다른 사람이 머지한 사실을 모른채 바로 develop에 머지를 하면 어떻게 될까요?
만약 머지하고 동시에 푸시를 했는데 다른 사람보다 조금 늦은 경우라면요?
# case 2. 최신화 되지 않은 develop 을 이용한 merge
1. 위와 동일하게 A가 develop 브랜치에서 feature/first 브랜치를 머지해두었습니다.
2. B가 fetch를 진행하지 않고 바로 develop 브랜치에서 feature/second 브랜치를 머지해서 푸시합니다
-> 이 push 명령은 거절되는데요. 바로 origin/develop과 로컬의 develop 브랜치가 다른 상태이기 때문이죠.
# 푸시 수행 결과
! [rejected] develop -> develop (fetch first)
error: failed to push some refs to'git URL'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.
3. 바로 푸시할 수 없으니 develop 브랜치를 fetch 하면 이런 상태가 됩니다
4. 이제 머지를 위해 pull을 받아서 develop에 A의 코드를 반영합니다.
-> 충돌이 발생합니다.
현재 feature/second 를 머지한 상태에서 A가 작업한 코드가 반영되도록 pull을 받았더니
case1과는 달리 충돌 시 코드 순서도 변경되었습니다.
당황하지 않고 차분하게 코드를 수정해주고, 커밋을 하면
이대로 Push로 마무리 합니다.
# case 3. upstream 을 이용한 merge
현재 upstream을 사용한 적이 없기 때문에, upstream을 생성해야 합니다.
# 1. 현재 원격 저장소 확인(명령어 결과에 origin만 있다면 upstream을 추가해야함)
git remote -v
upstream 원격 저장소를 추가합니다.
git remote add upstream <원본 저장소 URL>
그리고 생성한 upstream을 가져옵니다
git fetch upstream
그럼 소스트리에서 이렇게 확인할 수 있습니다.
이제 머지할 수 있는 환경이 되었습니다.
1.A가 develop 브랜치에서 feature/first 브랜치를 머지해놓은 상태
2. B의 feature/second 브랜치를 upstream을 이용해서 최신화
-> 머지 충돌 발생
$ git merge upstream/develop feature/second
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
3. B가 develop에서 feature/second 브랜치를 merge
-> 이때는 머지 충돌이 발생하지 않음 ( 당연함. 미리 했으니까)
'TWIL' 카테고리의 다른 글
[TWIL] DNS와 /etc/hosts (0) | 2025.04.13 |
---|---|
[TWIL] Quartz : Multi WAS 환경에서의 배치 스케줄링 방식 이해하기 (0) | 2025.04.05 |
[TWIL]CPU 과점유 시 확인해야 할 사항들 (0) | 2025.03.21 |
[TWIL] Ehcache Replication으로 세션공유하기 (2) | 2025.02.28 |
[TWIL] MariaDB - MHA 이중화를 알아보자 (0) | 2025.02.23 |