dev, stg, main 브랜치를 기준으로 Pull Request, cherry-pick, hotfix, rebase, reset, restore 작업 순서를 정리합니다.
이 문서는 Git 공식 문서의 pull, merge, rebase, cherry-pick, reset, restore, tag 동작 설명과 Gitea 공식 Pull Request 문서를 기준으로 작성했습니다.
핵심 요약
브랜치 운영에서 가장 중요한 기준은 아래와 같습니다.
| 상황 | 핵심 작업 |
|---|---|
dev → stg PR 전 |
dev를 최신화하고, stg에만 있는 커밋이 있는지 확인합니다. |
stg → main PR 전 |
main에만 있는 커밋이 있으면 stg에 먼저 반영합니다. |
stg → main PR 머지 후 |
main → stg → dev 순서로 최신 상태를 내려줍니다. |
main hotfix 후 |
main에 들어간 수정은 반드시 stg, dev로 역반영합니다. |
| 일부 커밋만 운영 반영 | cherry-pick용 브랜치를 main 기준으로 새로 만들어 필요한 커밋만 적용합니다. |
| 기능 브랜치 정리 | feature 브랜치를 최신 dev 위로 rebase한 뒤 PR을 생성합니다. |
| 파일 되돌리기 | 파일 단위는 restore, 커밋/브랜치 위치 변경은 reset을 사용합니다. |
git pull은 원격 변경을 가져온 뒤 현재 브랜치에 통합하는 명령입니다. 내부적으로 먼저 fetch를 수행한 뒤, 설정에 따라 merge 또는 rebase 방식으로 통합합니다.
Gitea의 Pull Request는 한 브랜치의 변경사항을 다른 브랜치로 병합하기 위해 요청하는 절차입니다. 따라서 PR을 만들기 전에는 base 브랜치와 compare 브랜치의 차이를 먼저 확인하는 것이 안전합니다.
1. 브랜치 역할 정리
이 문서에서는 아래 브랜치 흐름을 기준으로 설명합니다.
feature/* → dev → stg → main
↑ ↑
테스트 운영| 브랜치 | 역할 |
|---|---|
feature/* |
개별 기능 또는 이슈 작업 브랜치 |
dev |
개발 통합 브랜치 |
stg |
스테이징, 검수, 배포 전 테스트 브랜치 |
main |
운영 배포 기준 브랜치 |
hotfix/* |
운영 긴급 수정 브랜치 |
cherry/* |
특정 커밋만 운영에 반영하기 위한 임시 브랜치 |
기본 원칙은 아래와 같습니다.
- 기능 개발은
feature/*에서 진행합니다. - 기능 검증 전에는
feature/* → dev로 반영합니다. - 스테이징 검증 전에는
dev → stgPR을 생성합니다. - 운영 반영 전에는
stg → mainPR을 생성합니다. - 운영 긴급 수정은
main기준의hotfix/*브랜치에서 진행합니다. - 운영에 들어간 hotfix는 반드시
main → stg → dev순서로 내려줍니다.
운영 브랜치인
main에 직접 push하는 방식은 권장하지 않습니다. Gitea 보호 브랜치와 PR 승인 규칙을 사용하면 실수로 운영 이력을 바꾸는 위험을 줄일 수 있습니다.
2. dev → stg PR 요청 전에 할 작업
dev의 변경사항을 stg로 올리기 전에 dev가 최신인지, 작업 폴더가 깨끗한지, stg에만 존재하는 커밋이 있는지 확인합니다.
2-1. dev 브랜치로 이동
git checkout dev현재 브랜치가 dev인지 확인합니다.
git branchgit branch --show-current2-2. dev 최신화
git pull origin devgit pull origin dev는 원격 origin/dev의 변경사항을 가져온 뒤 현재 dev 브랜치에 통합합니다.
2-3. 변경사항 없는지 확인
git status정상적인 상태는 아래와 같습니다.
nothing to commit, working tree clean이 상태가 아니라면 아직 commit하지 않은 파일이나 충돌 중인 파일이 있는지 먼저 정리해야 합니다.
2-4. 원격 브랜치 정보 가져오기
git fetch origingit fetch origin은 원격 저장소의 최신 브랜치 정보를 로컬의 origin/* 원격 추적 브랜치에 반영합니다. 현재 작업 브랜치의 파일을 직접 바꾸지는 않습니다.
2-5. stg에만 있는 커밋 확인
git log --oneline origin/dev..origin/stg이 명령은 origin/stg에는 있지만 origin/dev에는 없는 커밋을 보여줍니다.
출력이 없다면 stg에만 존재하는 커밋이 없는 상태입니다.
출력이 있다면 stg에 dev가 아직 포함하지 않은 커밋이 있다는 의미입니다. 이 경우 dev → stg PR에서 Gitea가 브랜치 최신화가 필요하다고 표시하거나, 병합 전에 dev에 stg 변경사항을 먼저 반영해야 할 수 있습니다.
2-6. 충돌 가능성 확인
충돌 가능성을 더 직접적으로 보고 싶다면 테스트용으로 merge를 시도할 수 있습니다.
git checkout dev
git pull origin dev
git merge --no-commit --no-ff origin/stg충돌이 없다면 아래 명령으로 테스트 merge를 취소합니다.
git merge --abort충돌이 발생했다면 실제 PR에서도 충돌 가능성이 높습니다. 이 경우 충돌 원인을 확인한 뒤 dev에 stg 변경사항을 먼저 반영할지 결정해야 합니다.
2-7. dev를 원격에 push
dev의 변경사항이 정상이고 충돌 가능성을 확인했다면 원격에 push합니다.
git push origin dev그 다음 Gitea에서 PR을 생성합니다.
| 항목 | 값 |
|---|---|
| base | stg |
| compare | dev |
3. stg → main PR에서 outdated가 나오는 경우
stg가 최신이라고 생각했는데 stg → main PR에서 outdated 또는 update branch가 표시될 수 있습니다.
이 상황은 보통 main 브랜치에 stg가 아직 포함하지 않은 커밋이 있을 때 발생합니다.
예를 들어 운영 hotfix가 main에 먼저 들어갔고, 그 hotfix가 아직 stg에 반영되지 않았다면 stg → main PR은 base 브랜치인 main 기준으로 최신 상태가 아닐 수 있습니다.
3-1. main과 stg 차이 확인
먼저 원격 정보를 최신화합니다.
git fetch originmain에는 있지만 stg에는 없는 커밋을 확인합니다.
git log --oneline origin/stg..origin/main출력이 있다면 stg에 없는 커밋이 main에 존재한다는 의미입니다.
3-2. 원격 main을 기준으로 stg에 반영
로컬 main을 따로 최신화하지 않고 원격 main 기준으로 바로 반영하려면 아래처럼 진행합니다.
git checkout stg
git pull origin stg
git merge origin/main
git push origin stg이 방식은 origin/main을 직접 merge하므로, 로컬 main 브랜치가 최신이 아니어도 원격 main 기준으로 반영할 수 있습니다.
3-3. 로컬 main을 최신화한 뒤 stg에 반영
먼저 로컬 main을 최신화한 상태라면 origin/main 대신 main을 merge해도 됩니다.
git checkout main
git pull origin main
git checkout stg
git pull origin stg
git merge main
git push origin stg정리하면 다음과 같습니다.
| 상황 | 사용 명령 |
|---|---|
로컬 main을 최신화하지 않았음 |
git merge origin/main |
로컬 main을 최신화했음 |
git merge main |
3-4. outdated 방지 기준
stg → main PR에서 outdated를 줄이려면 base 브랜치인 main의 내용을 compare 브랜치인 stg에 먼저 합쳐야 합니다.
즉, 운영 반영 전 기준은 아래와 같습니다.
main에만 있는 커밋 → stg에 먼저 반영 → stg → main PR 생성 또는 갱신4. stg → main PR 머지 후 해야 할 작업
stg → main PR이 승인되어 main에 머지되면, 로컬과 하위 브랜치를 최신 상태로 맞춰야 합니다.
운영 기준 브랜치인 main이 변경되었기 때문에 이후 작업 기준도 main의 변경을 포함해야 합니다.
4-1. main 최신화
git checkout main
git pull origin main4-2. stg 최신화
git checkout stg
git pull origin stg4-3. dev를 stg 기준으로 맞추기
git checkout dev
git pull origin dev
git merge stg
git push origin dev이 작업은 stg에 반영된 운영 기준 변경사항을 dev에도 내려주는 작업입니다.
특히 main에 hotfix가 들어간 뒤 stg를 거쳐 dev에 내려주지 않으면, 이후 dev → stg PR에서 다시 update branch 또는 충돌 상황이 발생할 수 있습니다.
4-4. 운영 태그 생성
운영 배포 지점을 명확히 남기려면 main 브랜치에 annotated tag를 생성할 수 있습니다.
git checkout main
git pull origin mainPowerShell에서 여러 줄 메시지로 태그를 만들 때는 줄 끝에 백틱 문자인 `을 사용합니다.
git tag -a v1.0.1 `
-m "- A 기능 추가" `
-m "- B 요청사항 수정" `
-m "- C 토큰 처리"태그를 원격에 push합니다.
git push origin v1.0.1한 줄 메시지로 처리하려면 아래처럼 작성할 수 있습니다.
git tag -a v1.0.1 -m "A 기능 추가, B 요청사항 수정, C 토큰 처리"
git push origin v1.0.1로컬 태그를 삭제하려면 아래 명령을 사용합니다.
git tag -d v1.0.1원격 태그를 삭제하려면 아래 명령을 사용합니다.
git push origin --delete v1.0.15. stg → main cherry-pick 작업
stg의 모든 내용을 main에 올리면 안 되고, 특정 커밋만 운영에 반영해야 할 때는 cherry-pick을 사용합니다.
git cherry-pick은 기존 커밋이 만든 변경사항을 현재 브랜치에 새 커밋으로 적용하는 명령입니다. 공식 문서 기준으로 작업 폴더가 깨끗한 상태에서 수행하는 것이 전제입니다.
5-1. stg에는 있고 main에는 없는 커밋 확인
git fetch origin
git log --oneline origin/main..origin/stg이 명령은 origin/stg에는 있지만 origin/main에는 없는 커밋을 보여줍니다.
운영에 반영할 커밋 해시를 여기서 확인합니다.
5-2. main 기준으로 cherry-pick 브랜치 생성
가장 안전한 방식은 원격 main 기준으로 새 브랜치를 만드는 것입니다.
git fetch origin
git checkout -b cherry/stg-to-main-token-fix origin/main이렇게 하면 로컬 main이 오래되어 있어도 원격 main 최신 상태를 기준으로 cherry-pick 브랜치가 생성됩니다.
5-3. 로컬 main을 최신화한 뒤 브랜치 생성하는 방식
로컬 main을 먼저 최신화한 뒤 브랜치를 만들 수도 있습니다.
git fetch origin
git checkout main
git pull origin main
git checkout -b cherry/stg-to-main-token-fix main5-4. 원하는 커밋만 cherry-pick
생성된 cherry-pick 브랜치로 이동합니다.
git cherry-pick <커밋_해시>여러 커밋을 순서대로 적용하려면 아래처럼 실행할 수 있습니다.
git cherry-pick <첫번째_커밋_해시>
git cherry-pick <두번째_커밋_해시>또는 연속된 커밋 범위라면 아래처럼 사용할 수 있습니다.
git cherry-pick <시작_커밋_해시>^..<끝_커밋_해시>5-5. cherry-pick 충돌 처리
충돌이 발생하면 상태를 확인합니다.
git status충돌 파일을 수정한 뒤 add합니다.
git add <충돌_해결_파일>cherry-pick을 계속 진행합니다.
git cherry-pick --continuecherry-pick을 취소하고 이전 상태로 돌아가려면 아래 명령을 사용합니다.
git cherry-pick --abort5-6. PR 브랜치 push
git push origin cherry/stg-to-main-token-fixGitea에서 PR을 생성합니다.
| 항목 | 값 |
|---|---|
| base | main |
| compare | cherry/stg-to-main-token-fix |
5-7. PR 머지 후 main 최신화
PR이 main에 머지되면 로컬 main을 최신화합니다.
git checkout main
git pull origin main5-8. stg를 main과 강제로 맞춰야 하는 경우
일반적인 운영에서는 reset --hard를 사용하지 않는 것이 안전합니다.
다만 cherry-pick 이후 stg에 운영으로 보내지 않을 커밋이 남아 있고, 팀 기준상 stg를 main과 완전히 동일하게 맞춰야 한다면 아래 절차를 사용할 수 있습니다.
먼저 로컬 stg를 main과 동일하게 만듭니다.
git checkout stg
git fetch origin
git reset --hard origin/main이 작업은 로컬 stg의 커밋 위치와 작업 폴더를 origin/main과 동일하게 바꿉니다.
원격 stg까지 동일하게 바꾸려면 force push가 필요합니다.
git push --force-with-lease origin stg이 명령은 원격 stg의 이력을 바꾸는 작업입니다. 보호 브랜치에서는 차단될 수 있고, 다른 사람이 작업 중인 브랜치라면 커밋 유실 위험이 있습니다. 따라서 운영 규칙상 정말 stg = main으로 초기화해야 하는 경우에만 사용해야 합니다.
reset --hard와 force push는 공유 브랜치의 이력을 바꾸는 작업입니다. 실행 전에는git log --oneline --graph --decorate --all또는 Gitea 브랜치 비교 화면에서 삭제될 커밋이 없는지 확인하는 것이 안전합니다.
6. main hotfix 작업
운영 장애나 긴급 수정이 필요한 경우 main 기준으로 hotfix 브랜치를 생성합니다.
중요한 점은 hotfix가 main에 머지된 뒤 반드시 stg와 dev에도 내려가야 한다는 것입니다.
6-1. hotfix 브랜치 생성
git checkout main
git pull origin main
git checkout -b hotfix/urgent-feature6-2. 긴급 수정 commit
수정 후 변경 파일을 확인합니다.
git status파일을 add하고 commit합니다.
git add .
git commit -m "긴급 수정"원격에 push합니다.
git push origin hotfix/urgent-feature6-3. Gitea에서 PR 생성
| 항목 | 값 |
|---|---|
| base | main |
| compare | hotfix/urgent-feature |
PR을 검토한 뒤 main에 머지합니다.
6-4. main 최신화
PR 머지 후 로컬 main을 최신화합니다.
git checkout main
git pull origin main6-5. main → stg 반영
git checkout stg
git pull origin stg
git merge main
git push origin stg이 작업은 운영 hotfix를 스테이징 브랜치에도 반영하는 과정입니다.
6-6. stg → dev 반영
git checkout dev
git pull origin dev
git merge stg
git push origin dev이 작업까지 해야 이후 개발 브랜치에도 운영 hotfix가 포함됩니다.
6-7. hotfix 브랜치 삭제
PR 머지가 끝났고 더 이상 hotfix 브랜치가 필요 없다면 로컬 브랜치를 삭제합니다.
git branch -d hotfix/urgent-feature원격 브랜치도 삭제합니다.
git push origin --delete hotfix/urgent-featuregit branch -d는 병합된 브랜치만 안전하게 삭제합니다. 아직 병합되지 않은 브랜치를 강제로 삭제하려면 -D를 사용할 수 있지만, 커밋 유실 위험이 있으므로 일반적으로 권장하지 않습니다.
7. feature → dev rebase 작업
feature 브랜치에서 작업한 커밋을 최신 dev 위로 정리하고 싶을 때 rebase를 사용합니다.
rebase는 내 커밋들을 새로운 기준 브랜치 위에 다시 적용하는 방식입니다. 이 과정에서 커밋 해시가 바뀔 수 있으므로 이미 다른 사람과 공유한 브랜치에서는 주의해야 합니다.
rebase는 커밋 이력을 깔끔하게 만들 수 있지만, 이미 원격에 공유된 브랜치에서는 다른 사용자의 작업 기준을 바꿀 수 있습니다. 개인 feature 브랜치에는 유용하지만,
dev,stg,main같은 공용 브랜치에는 일반적으로 사용하지 않는 것이 안전합니다.
7-1. 최신 dev 준비
git checkout dev
git pull origin dev7-2. feature 브랜치에서 rebase
git checkout feature/issue-1
git rebase dev이 작업이 끝나면 feature/issue-1의 커밋들이 최신 dev 위로 다시 정렬됩니다.
7-3. rebase 충돌 처리
충돌이 발생하면 상태를 확인합니다.
git status충돌 파일을 수정한 뒤 add합니다.
git add <충돌_해결_파일>rebase를 계속 진행합니다.
git rebase --continue충돌 해결이 어렵거나 rebase 전 상태로 돌아가고 싶다면 아래 명령을 사용합니다.
git rebase --abort7-4. rebase 후 원격 feature 브랜치 push
feature 브랜치를 처음 push하는 경우라면 일반 push를 사용합니다.
git push origin feature/issue-1이미 원격에 올라간 feature 브랜치를 rebase했다면 커밋 해시가 바뀌었을 수 있습니다. 이 경우 일반 push가 거부될 수 있으므로 아래 명령을 사용합니다.
git push --force-with-lease origin feature/issue-1--force-with-lease는 원격 브랜치가 내가 마지막으로 확인한 상태에서 바뀌지 않았을 때만 강제 push를 허용합니다. 일반 --force보다 안전합니다.
7-5. PR 방식으로 dev에 반영
Gitea에서 PR을 생성합니다.
| 항목 | 값 |
|---|---|
| base | dev |
| compare | feature/issue-1 |
리뷰와 테스트가 끝난 뒤 PR을 머지합니다.
PR이 머지된 뒤 feature 브랜치를 삭제합니다.
git branch -d feature/issue-1
git push origin --delete feature/issue-17-6. 로컬에서 직접 merge하는 방식
PR을 사용하지 않고 로컬에서 직접 dev에 합치는 방식도 가능합니다.
git checkout dev
git merge feature/issue-1
git push origin devrebase가 정상적으로 끝났고 dev가 feature의 기준 커밋이면 fast-forward merge가 될 수 있습니다. 이 경우 별도의 merge commit 없이 dev 브랜치 포인터가 앞으로 이동합니다.
다만 팀이나 Gitea 보호 브랜치 정책을 사용한다면 직접 push보다 PR 방식을 사용하는 것이 좋습니다.
8. restore와 reset 사용 기준
restore와 reset은 둘 다 되돌리기에 사용되지만 목적이 다릅니다.
| 작업 | 권장 명령 | 의미 |
|---|---|---|
| add 취소 | git restore --staged . |
staged 상태만 취소하고 파일 수정은 유지합니다. |
| add 취소 | git reset |
기본적으로 --mixed처럼 동작하여 staged 상태를 취소합니다. |
| 파일 수정 취소 | git restore . |
작업 폴더의 수정 내용을 되돌립니다. |
| 최근 commit 취소, 수정 내용 유지 | git reset --soft HEAD~1 |
commit만 취소하고 add 상태는 유지합니다. |
| 최근 commit 취소, add도 취소, 수정 내용 유지 | git reset --mixed HEAD~1 |
commit과 add를 취소하고 파일 수정은 남깁니다. |
| 최근 commit과 수정 내용 모두 삭제 | git reset --hard HEAD~1 |
commit, add, 파일 수정 내용을 모두 버립니다. |
8-1. add 취소
git restore --staged .또는 아래 명령도 사용할 수 있습니다.
git reset8-2. 파일 수정 취소
git restore .이 명령은 작업 폴더의 수정 내용을 되돌립니다. 아직 commit하지 않은 수정 내용이 사라지므로 실행 전에 반드시 git status로 확인해야 합니다.
8-3. commit만 취소하고 수정 내용은 남기기
git reset --soft HEAD~1이 명령은 최근 commit만 취소합니다. 파일은 staged 상태로 남습니다.
8-4. commit과 add를 취소하고 수정 내용은 남기기
git reset --mixed HEAD~1--mixed는 git reset의 기본 동작입니다.
가장 자주 사용하는 commit 취소 방식은 아래 명령입니다.
git reset --mixed HEAD~1결과는 다음과 같습니다.
- commit 취소
- add 취소
- 수정 내용은 작업 폴더에 유지
8-5. commit과 수정 내용을 모두 버리기
git reset --hard HEAD~1이 명령은 최근 commit뿐 아니라 작업 폴더의 수정 내용까지 삭제합니다.
복구가 어려울 수 있으므로 운영 브랜치나 공유 브랜치에서는 특히 주의해야 합니다.
git reset --hard와git restore .는 작업 폴더의 수정 내용을 삭제할 수 있습니다. 아직 commit하지 않은 변경사항이 필요하다면 실행 전에git diff로 내용을 확인하거나 임시 commit, stash 등을 사용해 보관하는 것이 좋습니다.
9. 브랜치 차이 확인 명령
브랜치 운영 중에는 어느 브랜치에 어떤 커밋이 있는지 확인하는 것이 중요합니다.
9-1. stg에는 있고 dev에는 없는 커밋
git log --oneline origin/dev..origin/stgdev → stg PR 전에 확인하기 좋습니다.
9-2. main에는 있고 stg에는 없는 커밋
git log --oneline origin/stg..origin/mainstg → main PR에서 outdated가 나올 때 확인하기 좋습니다.
9-3. stg에는 있고 main에는 없는 커밋
git log --oneline origin/main..origin/stgstg의 어떤 커밋이 아직 운영 main에 들어가지 않았는지 확인할 때 사용합니다.
9-4. 현재 브랜치와 upstream 확인
git branch -vv현재 로컬 브랜치가 어떤 원격 브랜치를 추적하는지 확인할 수 있습니다.
9-5. 현재 작업 상태 확인
git statusPR, merge, rebase, cherry-pick, reset 전에는 항상 git status를 먼저 확인하는 것이 좋습니다.
10. 실무 체크리스트
PR 요청 전에는 아래 순서로 확인하면 실수를 줄일 수 있습니다.
git branch --show-current
git status
git fetch origin브랜치별 차이를 확인합니다.
git log --oneline origin/dev..origin/stg
git log --oneline origin/stg..origin/main
git log --oneline origin/main..origin/stg작업 브랜치가 깨끗한지 확인합니다.
git status필요하다면 테스트를 실행합니다.
./gradlew test프로젝트가 Maven 기반이라면 아래처럼 실행할 수 있습니다.
mvn test테스트 명령은 프로젝트 빌드 도구에 맞게 선택하면 됩니다.
결론
dev, stg, main 브랜치를 운영할 때 가장 중요한 것은 변경사항의 흐름을 한 방향으로 유지하는 것입니다.
일반 기능 개발은 아래 흐름을 따릅니다.
feature/* → dev → stg → main운영 hotfix는 반대로 아래 흐름으로 반드시 내려줘야 합니다.
main → stg → devstg → main PR에서 outdated가 발생하는 가장 흔한 이유는 main에만 있는 커밋이 stg에 반영되지 않았기 때문입니다. 이 경우 main의 내용을 stg에 먼저 merge한 뒤 PR을 갱신하는 것이 기본 해결 방향입니다.
일부 커밋만 운영에 반영해야 한다면 main 기준의 cherry/* 브랜치를 만들고 필요한 커밋만 cherry-pick하는 것이 안전합니다.
feature 브랜치는 최신 dev 기준으로 rebase하여 정리할 수 있습니다. 다만 rebase는 커밋 해시를 바꿀 수 있으므로 이미 공유된 브랜치에서는 --force-with-lease 사용 여부와 팀 정책을 반드시 확인해야 합니다.
파일 단위 되돌리기는 restore, 커밋이나 브랜치 위치 되돌리기는 reset을 기준으로 구분하면 됩니다.
참고 자료
- Git 공식 문서 - Git Reference: https://git-scm.com/docs
- Git 공식 문서 -
git merge: https://git-scm.com/docs/git-merge - Git 공식 문서 -
git rebase: https://git-scm.com/docs/git-rebase - Git 공식 문서 -
git cherry-pick: https://git-scm.com/docs/git-cherry-pick - Gitea 공식 문서 - Pull Request: https://docs.gitea.com/usage/pull-request
'프로그래밍 > Git' 카테고리의 다른 글
| Git 브랜치와 Worktree (0) | 2026.07.15 |
|---|---|
| Git 명령어 (0) | 2026.07.09 |
| Git 한글 파일명 깨짐 해결 (core.quotePath) (0) | 2026.05.09 |
| GitHub SSH 연결 오류 해결: Permission denied (publickey) 가이드 (0) | 2026.05.02 |
| 프로젝트 시작을 위한 환경 설정 및 핵심 명령어 가이드 (0) | 2026.05.02 |
댓글