Git Cherry-pick

특정 커밋만 골라서 다른 브랜치에 적용하기

Git Cherry-pick을 사용하여 특정 커밋을 다른 브랜치에 선택적으로 적용하는 방법을 설명한다. cherry-pick의 개념, 사용법, 충돌 해결, 실전 활용 시나리오를 다룬다.

Engineering
Git
DevOps
저자

Kwangmin Kim

공개

2023년 05월 13일

1 Cherry-pick이란?

Cherry-pick은 특정 커밋 하나(또는 여러 개)를 골라서 현재 브랜치에 적용하는 기능이다.

브랜치 전체를 merge/rebase하는 것이 아니라, 원하는 커밋만 선택적으로 가져온다.

main:      A --- B --- C --- D
                  \
feature:           E --- F --- G

# F 커밋만 main에 적용하고 싶다
git cherry-pick F

main:      A --- B --- C --- D --- F'

F’은 F와 같은 변경 내용을 가지지만, 새로운 커밋 해시를 가진 별개의 커밋이다.

2 기본 사용법

# 특정 커밋을 현재 브랜치에 적용
git cherry-pick abc1234
[main f9b2c3d] feat: Add payment gateway
 Date: Mon Jan 15 14:00:00 2024 +0900
 2 files changed, 47 insertions(+)

[main <새해시>] 형식으로 새로운 커밋이 생성된다. 원본 커밋(abc1234)과 날짜는 같지만 해시가 다른 새 커밋이 만들어진다.

# 여러 커밋을 한번에 적용
git cherry-pick abc1234 def5678 ghi9012
[main 1a2b3c4] feat: Add payment gateway
[main 5d6e7f8] feat: Add payment history
[main 9g0h1i2] feat: Add refund feature

순서대로 3개의 커밋이 생성된다.

# 연속된 커밋 범위 적용 (시작 커밋은 제외, 끝 커밋 포함)
git cherry-pick abc1234..ghi9012

# 연속된 커밋 범위 적용 (시작 커밋도 포함)
git cherry-pick abc1234^..ghi9012

2.1 커밋하지 않고 변경사항만 가져오기

# 변경사항을 Working Directory에 적용하되, 자동 커밋하지 않음
git cherry-pick --no-commit abc1234
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   src/payment.js
        new file:   src/payment-gateway.js

커밋이 생성되지 않고 변경사항이 staged 상태로 남는다. 여러 cherry-pick을 -n 으로 적용한 후 하나의 커밋으로 합칠 수 있다.

3 충돌 해결

Cherry-pick 중 충돌이 발생하면:

git cherry-pick abc1234

충돌 발생 시:

Auto-merging src/payment.js
CONFLICT (content): Merge conflict in src/payment.js
error: could not apply abc1234... feat: Add payment gateway
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
# 1. 충돌 파일 확인
git status
On branch main
You are currently cherry-picking commit abc1234.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   src/payment.js

You are currently cherry-picking commit abc1234. 메시지가 나타난다.

# 2. 충돌 파일을 열어서 수정 (충돌 마커 제거)
# <<<<<<< HEAD
# 현재 브랜치의 내용
# =======
# cherry-pick하려는 커밋의 내용
# >>>>>>> abc1234... feat: Add payment gateway

# 3. 충돌 해결 후 스테이징
git add src/payment.js

# 4. cherry-pick 계속 진행
git cherry-pick --continue
[main f9b2c3d] feat: Add payment gateway
 Date: Mon Jan 15 14:00:00 2024 +0900
 2 files changed, 47 insertions(+), 3 deletions(-)
# 또는 cherry-pick 취소 (원래 상태로 복원)
git cherry-pick --abort
Successfully aborted cherry-pick.

4 실전 시나리오

4.1 시나리오 1: 핫픽스를 여러 브랜치에 적용

main에서 긴급 버그를 수정한 후, 해당 수정을 develop 브랜치에도 적용해야 할 때:

# 1. main에서 버그 수정
git switch main
git commit -m "fix: Critical login bug"
# 이 커밋의 해시가 abc1234라고 가정

# 2. develop에 동일한 수정 적용
git switch develop
git cherry-pick abc1234

4.2 시나리오 2: feature 브랜치에서 일부 커밋만 릴리스

feature 브랜치에 여러 커밋이 있지만, 그 중 일부만 먼저 릴리스해야 할 때:

# feature 브랜치의 커밋 확인
git log feature/payment --oneline
ghi9012 feat: Add refund feature
def5678 feat: Add payment history
abc1234 feat: Add payment gateway
# 필요한 커밋만 main에 적용
git switch main
git cherry-pick abc1234 def5678
[main 1a2b3c4] feat: Add payment gateway
 Date: Mon Jan 15 14:00:00 2024 +0900
 2 files changed, 47 insertions(+)
[main 5d6e7f8] feat: Add payment history
 Date: Mon Jan 15 15:00:00 2024 +0900
 1 file changed, 23 insertions(+)

4.3 시나리오 3: 잘못된 브랜치에 커밋한 경우

main에 직접 커밋해버린 것을 feature 브랜치로 옮길 때:

# 1. main의 마지막 커밋 해시 확인
git log --oneline -1
# abc1234 feat: New feature (잘못 커밋됨)

# 2. feature 브랜치 생성 및 cherry-pick
git switch -c feature/new-feature
git cherry-pick abc1234

# 3. main에서 해당 커밋 제거
git switch main
git reset --hard HEAD~1

4.4 시나리오 4: release 브랜치에 핫픽스 적용

Git Flow에서 hotfix를 release 브랜치에 cherry-pick으로 적용:

# hotfix 커밋을 release 브랜치에 적용
git switch release/v2.0.0
git cherry-pick <hotfix-커밋해시>

5 Cherry-pick vs Merge vs Rebase

항목 Cherry-pick Merge Rebase
적용 범위 특정 커밋만 브랜치 전체 브랜치 전체
새 커밋 생성 O (복사본) O (병합 커밋) O (재배치)
원본 커밋 변경 없음 변경 없음 해시 변경
주 용도 선택적 적용 브랜치 통합 이력 정리

6 주의사항

경고
  • Cherry-pick된 커밋은 원본과 다른 해시값을 가진다. 같은 변경사항이 두 브랜치에 각각 다른 커밋으로 존재하게 된다.
  • 나중에 두 브랜치를 merge할 때 동일한 변경사항이 중복으로 적용될 수 있다. Git이 대부분 자동으로 처리하지만, 간혹 충돌이 발생할 수 있다.
  • Cherry-pick을 남발하면 이력 추적이 어려워진다. 브랜치 전체를 merge/rebase하는 것이 더 적합한 상황에서는 그 방법을 사용하자.
  • Cherry-pick은 해당 커밋의 변경사항만 적용한다. 그 커밋이 의존하는 이전 커밋의 변경사항은 포함되지 않으므로, 독립적이지 않은 커밋을 cherry-pick하면 문제가 생길 수 있다.

7 요약

명령어 동작
git cherry-pick <hash> 특정 커밋 적용
git cherry-pick A B C 여러 커밋 적용
git cherry-pick A^..C 범위 커밋 적용 (A 포함)
git cherry-pick -n <hash> 커밋 없이 변경사항만 적용
git cherry-pick --continue 충돌 해결 후 계속
git cherry-pick --abort cherry-pick 취소

Subscribe

Enjoy this blog? Get notified of new posts by email: