여러가지 이야기

[Git] Git branch 전략(Git-Flow), feature와 develop 브랜치 사이 작업 시 pull 전략 본문

study/GitHub

[Git] Git branch 전략(Git-Flow), feature와 develop 브랜치 사이 작업 시 pull 전략

jimddong 2025. 7. 11. 17:37

그동안 팀 협업 시 Git을 쓰긴 했지만, 보통은 각자 작업한 내용을 feature 브랜치를 만들어 push하고 develop으로 merge하는 방식이었다. 그런데 이번에 새로운 프로젝트를 진행하게 되면서, Git branch 전략 중 Git-Flow를 접하게 되었다. 

사실 나는 그간 여러 브랜치를 파는 게 개발적으로 단순 작업 분리 및 통합의 기능을 한다고 생각해왔었는데, 그 이상의 것을 한다는 걸 알게 되었다!
그 내용을 정리해보려 한다.

본론부터 말하자면 브랜치 전략은 팀 프로젝트 코드를 작업을 나누어 개발하는 것에서 더 나아가, 검증 및 배포 후 운영하는 데 있어서 필요하다. 왜냐면 Git-Flow에서는 단순 feature, develop이 끝이 아니라 release, main 브랜치까지 존재하기 때문이다.

 

Git Flow 구조를 직접 그림으로 그려보았다.

feature 브랜치

feature 브랜치는 개인이 할당 받은 작업을 처리하는 개인 개발용 브랜치라고 보면 된다. 그림에서 볼 수 있듯이 feature 브랜치는 develop에서 뻗어나와, 작업이 끝나면 다시 develop으로 합쳐진다. 즉, develop에서 시작하여 만든 브랜치에서 작업을 하고 develop으로 push한다는 것이다.

git checkout -b feature-project-init

// 해당 브랜치에서 코드 작업 후
git add .
git commit -m "feat: Initial project setting"
git push origin feature-project-init

// Develop 브랜치에서 merge
git pull origin feature-project-init

 

develop 브랜치 (Dev)

develop 브랜치는 말 그대로 개발 브랜치이다. 여러 feature 브랜치 내용들이 병합된 작업물이다. 

 

 

release 브랜치 (QA)

develop 브랜치의 내용을 release 브랜치에서 검증한다. 검증 브랜치로, 최종 배포인 main 브랜치에 가기 전 통합 테스트를 진행한다.

그런데 만약 검증 단계인 release(QA) 브랜치에서 버그나 문제가 생겼다면 어떻게 해야할까? 이 때는 main(Prod)으로 바로 직행하지 않고 develop으로 돌아가야한다. (롤백)

 

이처럼 롤백에서는, develop에서 수정된 내용을 다시 release에 병합 하는 검증 과정을 문제가 모두 해결될 때까지 반복한다.

이런 과정이 첫 번째였다면 알파 테스트, 두 번째였다면 베타 테스트 등으로 부른다.

 

 

main 브랜치 (Prod)

이제 마지막 브랜치 main이다. 실제 운영 환경 브랜치로 최종 배포만 이뤄지는 곳이다.

실제로 나의 경우, 터미널에서 bastion 서버를 거쳐 실제 배포 서버(ssh)로 들어가 develop (release는 생략) 브랜치의 내용을 main 브랜치로의 병합하는 과정을 경험할 수 있었다.

main에 반영하는 방법은 크게 두 가지이다.

더보기

1. 운영 서버에서 수동 배포하기

main 브랜치에서 git pull origin develop을 통해 병합(merge)하면 되는데, 코드 충돌이 발생하면 터미널에서 수동으로 해결해야한다는 번거로움이 있다.

 

2. Git Action 활용하기

정확히는 프로젝트 GitHub에 들어가 develop에서 main으로 pull하게끔 PR(pull request)을 날려 수동 배포하는 것이다.

이때 develop 기능을 main 반영에 반영할 때 Git Actions의 CI/CD 및 CodeDeploy가 쓰일 수 있다.

CI/CD 자동 배포로, Git Action이 CI/CD 파이프라인을 자동으로 실행시키기에 PR만 날려주면 직접 1번과 같은 명령어 입력 없이 배포(main 브랜치에 최종 반영)가 가능하다.

 Git Action을 활용한 CI/CD 방법은 추후 다시 정리해보겠다!

추가로 배포 서버 내에서 변경된 rds DB 스키마를 수정하는 등의 작업도 하기도 했다.

 

추가로, 이렇게 각 브랜치 업데이트별로 버전을 붙이는 작업을 Tagging이라 하는데, Tag는 각 개발 시점의 버전을 맞춰 기록하기 위해 쓰인다.

 

그런데 다시 위 사진을 보면 develop, release 브랜치와 main 브랜치의 버전이 조금씩 차이가 나는 걸 확인할 수 있다.

만약 계속 반복적으로 이뤄지는 펜딩(release ↔ main, 검증 후 수정과 merge 반복)이 있었다면, release와 develop 사이에서는 계속해서 새로운 각 커밋의 release note 버전이 존재할 것이다.

 

main 브랜치에는 검증하여 최종적으로 통과된 버전만 올라가게 해야하므로, 버전이 사진과 같이 순차적이지 않을 수 있다!

(ex. v1.0.0 → v1.3.2)

* 숫자 차이가 클수록 QA 후 배포하려는 과정에서 엄청난 핑퐁이 있었다고 생각하면 된다고 한다..

 

다시 정리해보자면 아래와 같다

더보기

🔢 작업 순서 (feature → dev → release → main) & Tagging

  1. feature(개인 개발용, 사진 상 dev 브랜치 왼쪽 가생이들) 브랜치에서 작업 후 dev 브랜치로 병합
  2. 여러 feature들이 모인 dev를 release(검증용)으로 병합(merge)
    - release note - 비개발자들이 볼 수 있는 documentation, 깃헙 형식이 아닌 파일 형식
    (ex. release note (v1.0.0))
  3. 검증 통과 시 최종적으로 main에도 push
    (ex. main branch (v1.1.0))

develop, release, main 3개 브랜치가 모두 동일한 버전, 같은 커밋( = 한 release note 기준으로 굴러가기)으로 관리하는 과정은 중요하기에 relelase note도 필수다.

 

+ Git 유의사항 (pull & merge)

추가로 내 작업이 있는 feature 브랜치에서 develop 브랜치로 push하기 전에 develop에서 다른 사람들의 작업이 추가되었다면, feature 브랜치에서 develop의 내용을 가져와 합친 후 (혹시 충돌 내용이 있다면 고쳐야함) develop으로 push할 수 있다.
하지만 아래처럼 에러가 발생하기도 했다.

 * branch            develop    -> FETCH_HEAD
힌트: You have divergent branches and need to specify how to reconcile them.
힌트: You can do so by running one of the following commands sometime before
힌트: your next pull:
힌트: 
힌트:   **git config pull.rebase false  # merge**
힌트:   git config pull.rebase true   # rebase
힌트:   git config pull.ff only       # fast-forward only
힌트: 
힌트: You can replace "git config" with "git config --global" to set a default
힌트: preference for all repositories. You can also pass --rebase, --no-rebase,
힌트: or --ff-only on the command line to override the configured default per
힌트: invocation.
fatal: Need to specify how to reconcile divergent branches.
```

이 메시지는 git pull 전략을 설정하지 않아서 나오는 것인데, 위에서 나오는 pull 전략 3가지에 대해 정리해보겠다.

 

Git pull 전략 3가지

1. ⭐️ (merge) git config pull.rebase false (= git merge develop)
: 기본적인 merge

  • 협업, 팀 프로젝트에서 많이 쓰이는 기본 전략
  • 아래와 같이 커밋 히스토리에도 Merge branch 'develop' into feature/... 같은 merge commit이 남는다.
*   f7a3d45  ← merge commit (feature와 develop 병합)
|\
| * d43c123  ← feature 브랜치 작업 ⬆️
|/
* 53d8210  ← develop 최신 ⬆️
  • 히스토리 추적이 쉽고, 변경 흐름이 명확히 드러난다.
  • 여러 명이 같은 브랜치 작업할 때 나는 충돌 관리(한 번에 처리)도 쉽다.

 

 

2. (rebase) git config pull.rebase true (= git rebase develop)
: 커밋 히스토리를 깔끔하게 정리

  • 개인 작업용 브랜치 정리할 때 좋음, 팀에서는 신중하게 써야 함 (충돌 추적이 어려워질 수도 있어서) 난이도 ⬆️
  • 커밋 히스토리가 일직선으로 깔끔해진다.
  • 병합 커밋(merge commit)이 생기지 않는다.
* d43c123  ← feature 커밋 (rebase 후 새로 생성됨)
* 53d8210  ← develop 최신 ⬆️
  • 충돌이 났을 때도 해결해야 하지만(커밋마다 처리), Git이 "이 커밋은 어디서 왔는지" 파악하기 어려울 수 있음
    (충돌 발생 시 rebase 명령어로 새 커밋을 만들어 해결)
git rebase develop

# 충돌 발생
# 수정 후
git add .

# 다음 커밋으로 계속 진행
git rebase --continue

# 또 충돌? 똑같이 반복
git add .
git rebase --continue

# 만약 중단하고 싶으면
git rebase --abort

 

 

 

3. (fast-forward only) git config pull.ff only: 커밋 충돌이 없는 경우에만 진행

 

 

위에서 말했듯이 feature 브랜치에서 업데이트 된 develop의 내용을 가져와 합친 후 충돌 내용이 있다면 고쳤어야했기에,

즉 내가 한 git pull은

merge 후 conflict 해결

= git config pull.rebase false 

= git fetch develop + git merge develop 이었다.

결론적으로 작업 시 다음과 같은 전략을 쓰는 것이 좋다.

// feature에서 작업하고
git add .
git commit -m "feat: XXX 기능 추가"
git push origin feature/XXX

// 만약 feature 브랜치에서 develop merge
git checkout feature/XXX
git config pull.rebase false    # merge 전략으로 설정
git pull origin develop 
git push origin feature/XXX     # 충돌 해결 사항도 포함해서 push

// develop <- feature PR 보내기

'study > GitHub' 카테고리의 다른 글

[GitHub] 작업물을 올려보자 (remote, add, commit, push)  (0) 2024.01.12