블로그로 돌아가기

git cherry-pick: 여러 커밋, 브랜치, 충돌까지

2026년 9월 12일

한 줄 요약: git cherry-pick <sha>는 아무 브랜치의 커밋 하나를 현재 브랜치로 복사합니다 — 같은 패치, 새 SHA, 이동된 이력은 없습니다. 커밋 여러 개는 SHA를 나열하거나 범위를 쓰세요(git cherry-pick A..B); 범위는 A를 제외하므로 포함하려면 A^..B로 쓰세요. 충돌에서 멈추면 해결하고, git add하고, git cherry-pick --continue입니다. Cherry-pick은 특정 수정을 옮길 때의 도구입니다 — 상대 브랜치의 전부가 필요하면 merge나 rebase를 쓰세요.

git cherry-pick은 실제로 무엇을 할까?

Cherry-pick은 기존 커밋을 가져와 그 diff를 현재 브랜치에 새 커밋으로 적용합니다. 원본 커밋은 제자리에 남고, 복사본은 새 SHA를 받습니다. Git은 아무것도 “이동”하지 않습니다 — 나중에 그 커밋이 왜 옛 브랜치에 여전히 보이는지 궁금해하는 사람들이 보고 있는 것이 정확히 이 현상입니다.

이 복사-가 아니라-이동 모델이 cherry-pick이 맞는 도구인 순간을 결정합니다:

  • main에 지금 필요한 건 피처 브랜치의 수정 하나인데, 나머지를 머지하기는 싫을 때.
  • 잘못된 브랜치에 커밋된 핫픽스를 올바른 브랜치로 내려야 할 때.
  • main에서 절대 머지하지 않는 릴리스 브랜치에 패치를 재생해야 할 때.

짝이 되는 기술은 잘못이었던 커밋을 빼내는 법입니다 — 그 기계적 절차는 git undo last commit: keep the changes에서 다룹니다.

다른 브랜치에서 커밋을 cherry-pick하는 방법은?

SHA를 찾고, 대상 브랜치로 바꾸고, pick합니다:

# 1. 소스 브랜치에서 커밋 찾기
git log feature/payment-fix --oneline -5

# 2. 받아야 할 브랜치로 전환
git switch main

# 3. 가져오기
git cherry-pick 1a2b3c4

알아둘 편의 둘:

  • git cherry-pick <branch>는 그 브랜치의 tip 커밋을 pick합니다 — 편리하지만, “tip”이 무엇인지에 대한 낡은 머릿속 모델로 실수하기도 쉽습니다.
  • pick 후 git log -1 --stat가 무엇이 내려왔는지 확인해줍니다. 읽는 데 일 초, revert 한 번을 아껴줍니다.

커밋들은 feature/payment-fix에 그대로 남아 있습니다 — 그 브랜치는 마음껏 지워도 됩니다. main 위에 pick된 복사본은 자기 SHA가 있고 옛 커밋에 의존하지 않습니다.

커밋 여러 개를 cherry-pick하는 방법은?

세 가지 모양, 원하는 빈도 순으로:

# 1. 명시적 나열 — 나열한 순서대로 pick
git cherry-pick 1a2b3c4 5d6e7f8

# 2. 범위 — A 이후부터 B까지 전부
git cherry-pick A..B

# 3. A를 포함하는 범위
git cherry-pick A^..B

A..B vs A^..B 구분이 고전적인 깜짝입니다: A..BA제외합니다. git log로 범위를 그리고 oldest..newest를 pick하면 가장 오래된 커밋이 조용히 빠집니다. “가장 오래된 몇 개, 순서대로”가 목표라면 oldest^..newest로 쓰세요 — off-by-one이 사라집니다.

세 번의 pick을 한 커밋으로 접으려면 -n / --no-commit으로 커밋 없이 스테이징한 뒤 한 번 커밋합니다:

git cherry-pick -n 1a2b3c4 5d6e7f8
git commit -m "Backport: payment retry fixes"

git cherry-pick이 안 될 때는?

실제 원인 넷, 빈도 순으로:

1. 충돌이 pick을 멈췄다. Git이 패치를 적용하다가 양쪽 브랜치에서 바뀐 줄을 만나 시퀀스 중간에 멈춥니다:

# 파일들을 해결한 뒤:
git add <resolved-files>
git cherry-pick --continue   # 또는 --abort로 pick 이전 상태로 복귀

--continue는 선택도 아니고 암시도 아닙니다 — 실행하기 전까지 당신은 멈춰 선 cherry-pick 시퀀스 안에 있고, git status도 계속 그렇게 말해줄 겁니다.

2. pick이 비어 있다 (“The previous cherry-pick is now empty”). 변경이 이미 이 브랜치에 있습니다 — 종종 이전 pick이나 squash된 머지 때문에. git cherry-pick --skip으로 건너뛰거나, 표식이 정말 필요하면 --allow-empty로 빈 커밋을 강제하세요.

3. 그 커밋이 머지 커밋이다. 머지는 부모가 둘이라 “이 diff를 적용하라”는 말이 모호합니다 — git은 추측하는 대신 거부합니다. 어느 부모 기준으로 diff하는지 말해주세요:

git cherry-pick -m 1 <merge-sha>   # parent 1 = 머지*당한* 쪽 브랜치

4. 잘못된 작업 트리 또는 detached HEAD. Pick은 HEAD가 가리키는 곳에 내려앉습니다. Pick 전에 git branch --show-current를 실행하세요; 아무것도 출력하지 않으면 detached HEAD라서, 브랜치를 바꾸는 순간 그 커밋은 고아가 됩니다.

cherry-pick vs merge vs rebase: 언제 무엇을?

명령대상에 내려오는 것이력이럴 때
git cherry-pick <sha>지명한 커밋(들)만복사, 새 SHA특정 수정 하나가 지금 움직여야 할 때
git merge <branch>브랜치 위의 전부머지 커밋 또는 fast-forward브랜치 전체가 필요하고 분기가 보이길 원할 때
git rebase <base>브랜치 커밋 전부, 재생선형, SHA 재작성브랜치를 깔끔한 선형 흐름으로 원할 때
git revert <sha>커밋의 역방향되돌리기 커밋 추가공유 이력에 내려간 커밋을 되돌려야 할 때

한 줄 규칙: cherry-pick은 선택을 옮기고, merge와 rebase는 전부를 옮깁니다. 브랜치와 “동기화”하려고 cherry-pick을 뻗는 건 사실 merge가 필요하다는 신호입니다 — 그 브랜치가 포크의 main vs upstream이라면 전체 절차는 sync a fork with upstream, step by step에 있습니다.

건너뛸 습관 하나: 같은 커밋을 여러 브랜치에 장기간 cherry-pick하기. 소스 브랜치의 모든 미래 수정이 또 pick을 요구하고, 언젠가 브랜치들은 흩어집니다. 릴리스 브랜치로의 백포트는 정상적인 패턴입니다; 영구 평행우주는 아닙니다.

cherry-pick 워크플로우, 요약

git log <source-branch> --oneline -5   # SHA(들) 찾기
git switch <target-branch>             # 올바른 자리에 착지
git cherry-pick A^..B                  # 범위, 나열, 또는 단일 SHA
# 충돌 시: 해결 → git add → git cherry-pick --continue
git log -1 --stat                      # 무엇이 내려왔는지 확인

찾고, 바꾸고, pick하고, 확인합니다. 이 명령은 값어치 없는 위험한 명성을 갖고 있습니다 — diff는 적용되거나, 멈춰서 이유를 말해줍니다. 진짜로 파괴적인 실수는 잘못된 브랜치에 pick하는 것뿐이고, push 전의 git log -1이 그 하나를 놓치기 어렵게 만들어줍니다.

— mrsaynothing

Get the next one by email

One email per post. No spam, no algorithms.

self-hosted · no third parties · one-click unsubscribe

what is this?

Cron vs systemd 타이머: 무엇을 써야 할까?

글이 마음에 드셨나요? 제 본업이 바로 이런 일입니다. 저를 고용하세요