IT/Git & GitHub

main에 쌓인 커밋 구조조정하기

iamhyeon 2025. 11. 30. 14:36

main에서 전부 작업 백업 브랜치 만들기 → main 초기화 → 새 브랜치로 cherry-pick → 백업 브랜치 삭제

이런 상황을 만날 수 있다.

“원래는 feature/... 브랜치에서 작업했어야 하는데,
귀찮아서 그냥 main에서 다 해버렸다…”

이미 커밋도 여러 개 쌓였고, 리모트에도 푸시까지 해버렸다.
이 상태에서 히스토리를 말끔하게 정리하고 싶다면, 다음과 같은 전략을 사용할 수 있다.

  1. 현재 main 상태를 통째로 백업 브랜치로 복사
  2. main을 초기 커밋 시점으로 되돌리기
  3. 새 기능 브랜치를 하나 만들고,
  4. 백업 브랜치에 있는 필요한 커밋들만 cherry-pick
  5. 작업이 끝나면 백업 브랜치를 삭제

 


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   # 리모트에도 있다면

 

 

 

  1. 지금 상태를 반드시 백업 브랜치로 살려놓고
  2. 메인 히스토리를 reset + force push로 정리한 다음
  3. 필요한 커밋만 새 브랜치로 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