main에서 전부 작업 → 백업 브랜치 만들기 → main 초기화 → 새 브랜치로 cherry-pick → 백업 브랜치 삭제
이런 상황을 만날 수 있다.
“원래는 feature/... 브랜치에서 작업했어야 하는데,
귀찮아서 그냥 main에서 다 해버렸다…”
이미 커밋도 여러 개 쌓였고, 리모트에도 푸시까지 해버렸다.
이 상태에서 히스토리를 말끔하게 정리하고 싶다면, 다음과 같은 전략을 사용할 수 있다.
- 현재 main 상태를 통째로 백업 브랜치로 복사
- main을 초기 커밋 시점으로 되돌리기
- 새 기능 브랜치를 하나 만들고,
- 백업 브랜치에 있는 필요한 커밋들만 cherry-pick
- 작업이 끝나면 백업 브랜치를 삭제
1. main 브랜치로 이동
git checkout main
- 현재 작업 중인 브랜치와 상관없이, 기준이 될 main 브랜치로 이동하는 명령어이다.
- 모든 작업의 출발점은 main에서 시작한다.
2. 백업 브랜치 만들기 (현재 main 상태 보존)
git branch backup-main
- 현재 HEAD(=main의 최신 커밋)를 가리키는 새 브랜치 backup-main을 생성한다.
- 이 시점에서 backup-main은 “메인에서 작업을 다 해둔 상태”를 그대로 보존하는 스냅샷 브랜치 역할을 한다.
포인트: 이 브랜치를 만들어 두면, main 히스토리를 막 지워도
“혹시 실수했나?” 싶을 때 언제든지 backup-main에서 복구할 수 있다.
3. main을 초기 커밋으로 되돌리기 (reset)
이제 main을 원래 깔끔한 상태(초기 커밋)로 되돌린다.
여기서 사용할 명령어가 git reset --hard이다.
git reset --hard abc1234
- abc1234는 초기 커밋(또는 되돌리고 싶은 기준 커밋)의 해시라고 가정
- --hard 옵션은 해당 커밋 시점으로 덮어쓴다.
- 워킹 디렉토리
- 스테이징 영역
- HEAD
주의: --hard는 작업 중이던 변경 내용도 날려버리므로,
꼭 필요할 때만 사용해야 한다.
하지만 이미 backup-main으로 전체 상태를 백업했다면 비교적 안전하다.
3-1. 리모트 main까지 덮어쓰기 (force push)
로컬 main만 되돌리면 리모트와 상태가 달라지므로, 리모트 main도 동일한 커밋을 가리키도록 강제로 맞춰준다.
git push origin main --force
- --force는 리모트의 히스토리를 현재 로컬 브랜치 기준으로 덮어쓰는 옵션
- 이미 다른 사람이 main을 기반으로 작업 중이라면 매우 위험할 수 있으므로,
혼자 쓰는 저장소가 아니면 꼭 팀원과 상의 후 사용해야 한다.
이 시점에서:
- main → 초기 커밋 상태 (깨끗한 기본 브랜치)
- backup-main → 작업이 모두 쌓여 있는 상태 (히스토리 백업용)
4. 새 기능 브랜치 생성
이제 앞으로 작업을 이어갈 새 브랜치를 만든다.
git checkout -b feature/service
- -b 옵션은 브랜치 생성 + 체크아웃을 한 번에 수행하는 옵션이다.
- 기준은 현재 브랜치(main)의 최신 커밋이다.
→ 초기 커밋에서 출발하는 feature/service 브랜치가 된다.
5. backup-main에서 커밋 cherry-pick 하기
backup-main에 쌓여 있던 커밋들 중,
정말로 feature/service에 가져오고 싶은 커밋만 선택해서 옮기면 된다.
이때 사용하는 명령이 git cherry-pick이다.
5-1. cherry-pick 기본 형태
git cherry-pick <커밋해시>
- <커밋해시>는 backup-main 브랜치에 있는 커밋의 해시이다.
- 순서가 중요한 경우, 원래 커밋이 쌓인 순서대로 cherry-pick해야 충돌과 꼬임을 줄일 수 있다.
5-2. 여러 개 커밋을 순서대로 적용
예를 들어 backup-main에 아래 커밋들이 있다고 해보자.
- aaa1111 — 서비스 인터페이스 추가
- bbb2222 — 서비스 구현 추가
- ccc3333 — 테스트 코드 추가
- ddd4444 — 리팩토링
그렇다면 feature/service에서 다음과 같이 순서대로 cherry-pick 할 수 있다.
git cherry-pick aaa1111
git cherry-pick bbb2222
git cherry-pick ccc3333
git cherry-pick ddd4444
cherry-pick 도중 충돌(conflict)이 발생하면
- 파일을 직접 수정해서 충돌 해결
- git add <파일>
- git cherry-pick --continue
흐름으로 이어가면 된다.
6. 새 브랜치를 리모트에 푸시
기능 브랜치 구성이 끝났다면, 이제 리모트에 올린다.
git push -u origin feature/service
- -u 옵션은 로컬 브랜치와 리모트 브랜치를 연결(tracking)해준다.
- 이후부터는 git push, git pull만으로도 손쉽게 동기화할 수 있다.
저장소 구조
- main → 초기 커밋 기준, 깔끔한 상태
- feature/service → 필요한 커밋들만 cherry-pick해서 구성한 작업 브랜치
- backup-main → 이전 main의 전체 흔적(백업용)
로컬 브랜치 목록 확인
git branch
원격 브랜치 목록 확인
git branch -r
로컬+원격 브랜치 전체 목록 확인
git branch -a
7. 정리가 끝났다면, 백업 브랜치 삭제
구조 정리가 잘 되었고, 더 이상 이전 상태로 돌아갈 필요가 없다면
backup-main 브랜치를 정리해도 된다.
7-1. 로컬 브랜치 삭제
git branch -d backup-main
- -d 옵션은 “완전히 병합된 브랜치만 삭제”하는 옵션이라 조금 안전하다.
- 강제로 지우고 싶다면 -D 옵션을 쓸 수 있다.
- git branch -D backup-main
7-2. 리모트 브랜치 삭제 (만약 올려둔 경우)
git push origin --delete backup-main
- 리모트 저장소에서 backup-main 브랜치를 삭제한다.
- 만약 remote에 올리지 않았다면 이 단계는 생략해도 된다.
전체 흐름
# 1. main 기준으로 백업 브랜치 만들기
git checkout main
git branch backup-main
# 2. main을 초기 커밋으로 되돌리고, 리모트에도 강제 반영
git reset --hard abc1234 # 초기 커밋 해시
git push origin main --force
# 3. 새 기능 브랜치 생성
git checkout -b feature/service
# 4. backup-main에서 필요한 커밋만 순서대로 cherry-pick
git cherry-pick <commit1>
git cherry-pick <commit2>
git cherry-pick <commit3>
git cherry-pick <commit4>
# 5. 새 브랜치를 리모트에 푸시
git push -u origin feature/service
# 6. 백업 브랜치 정리 (선택)
git branch -d backup-main
# git push origin --delete backup-main # 리모트에도 있다면
- 지금 상태를 반드시 백업 브랜치로 살려놓고
- 메인 히스토리를 reset + force push로 정리한 다음
- 필요한 커밋만 새 브랜치로 cherry-pick해서 가져온다.
'IT > Git & GitHub' 카테고리의 다른 글
| Git 핵심 개념 (0) | 2025.10.12 |
|---|---|
| Git과 Github - 개발자가 알아야 할 버전 관리의 시작점 (0) | 2025.10.12 |
| Git Merge 옵션 : --ff, --no-ff, --squash (1) | 2025.08.29 |
| Git 커밋 메시지 규칙 (0) | 2024.10.26 |
| GitHub (0) | 2024.08.03 |