여러 커밋을 체리 피킹하는 방법


874

두 개의 지점이 있습니다. 커밋은 a다른있는 동안, 하나의 머리 b, c, d, ef위에 a. 나는 이동하려면 c, d, ef커밋하지 않고 첫 번째 분기로 b. 벚꽃이 그것을 선택 사용하기 쉬운 : 체크 아웃 첫 번째 지점을 하나씩 체리 - 선택 c에를 f먼저에 두 번째 지점을 리베이스. 그러나 모든 체리 - 선택할 수있는 방법이있다 c- f하나 개의 명령은?

다음은 시나리오에 대한 시각적 설명입니다 ( JJD 덕분에 ).

여기에 이미지 설명을 입력하십시오


3
언급 한 rebase가 실제로 질문과 관련이없는 것입니까? ( 나중에 b기초 하고 싶을 수도 f있지만, 체리 따기와는 아무런 관련이 없습니다.)
Superole

답변:


1280

Git 1.7.2는 다양한 커밋을 체리로 선택하는 기능을 도입했습니다. 로부터 릴리스 노트 :

git cherry-pick커밋 범위를 선택하는 법을 배웠습니다 (예 : cherry-pick A..Bcherry-pick --stdin) git revert. 그러나 이것들은 더 나은 시퀀싱 컨트롤 rebase [-i]이 지원하지 않습니다 .

커밋에서 A커밋 B( ) A보다 오래된 커밋 을 모두 선택하려면 B다음을 실행하십시오.

git cherry-pick A^..B

A 자체 를 무시 하려면 다음을 실행하십시오.

git cherry-pick A..B

(신용은 damian, JB Rainsberger 및 sschaef에게 간다)


249
"체리 픽 A..B"형식에서 A는 B보다 오래된 것이어야합니다. 순서가 잘못된 경우 명령이 자동으로 실패합니다.
damian

294
또한, 이것은 A를 체리 픽하지 않고 오히려 A 이후의 모든 것을 포함하여 B까지 포함합니다.
JB Rainsberger

455
A just type을 포함 시키려면git cherry-pick A^..B
kiritsuku

17
당신이 1.7.1 자식 또는 이전 할 수 없습니다 업데이트가있는 경우에, 당신은 꽤 빨리 실행하여 순서대로 체리 선택할 수 있습니다 git cherry-pick f~3다음 git cherry-pick f~2에 등까지 git cherry-pick f내가 빨리 수와 실행 이전 명령 변경할 수 있습니다됩니다 있도록 위쪽 화살표를 눌러 ( 대부분의 콘솔에서 비슷해야합니다).
David Mason

19
이 구문은 브랜치 이름에서도 작동한다는 것을 아는 것이 좋습니다. git cherry-pick master..somebranch마스터 이후 이미 분기에 대한 모든 커밋을 선택하고 (이미 마스터에 기반한다고 가정) 현재 분기에 적용합니다.
Tor Klingberg

102

가장 간단한 방법은 onto옵션을 사용하는 것 rebase입니다. 가정에서 분기되는 현재 완료가 amybranch로라고하며이 이동할하는 지점입니다 c- f에.

# checkout mybranch
git checkout mybranch

# reset it to f (currently includes a)
git reset --hard f

# rebase every commit after b and transplant it onto a
git rebase --onto a b

1
감사합니다! git checkout secondbranch && git rebase mybranch전체 답변을 추가
하겠습니까?

1
이 답변은이 시나리오에서 어느 커밋이 어느 머리인지를 이해하는 데 많은 도움이되었습니다. 그리고 : rebase의 대화식 모드도 사용할 수 있습니다 . 감사합니다, @Charles!
올리버

1
이 방법의 장점 --interactive은 시퀀스에서 커밋을 제거하거나 "체리 픽"이전에 다시 커밋 하는 데 사용할 수 있다는 것 입니다. +1
Michael Merickel

이것은 독창적 인 명령이며 머리를 감싸기에는 약간 까다 롭지 만 놀라운 일입니다.
Valerio

당신이 논쟁 중 하나 ( 이 예제에서) 로 리베이스하고 싶지 않다는 커밋을 제공해야한다는 것은 당연 b하지만, 이것은 나를 위해 일했습니다.
asontu

85

또는 요청 한 원 라이너 :

git rebase --onto a b f

5
간결성을 위해 이것이 최선의 대답입니다.
네이트 챈들러

9
당신은 하나의 같은 지점을 체크 아웃해야 추가 편집해야 - F는가 (지점 반대) 커밋 경우 Upvoted하지만 분리 된 HEAD 상태에서 당신을 떠나 아래 답
Mr_and_Mrs_D

68

당신의 직렬 조합을 사용할 수 있습니다 git rebasegit branch다른 지점에 커밋의 그룹을 적용 할 수 있습니다. wolfc 가 이미 게시 한 것처럼 첫 번째 명령은 실제로 커밋을 복사합니다. 그러나 그룹의 최상위 커밋에 분기 이름을 추가 할 때까지 변경 내용이 표시되지 않습니다.

새 탭에서 사진을여십시오.

워크 플로우

명령을 텍스트 형태로 요약하려면 :

  1. 열기 gitk이 명령을 사용하여 독립적 인 프로세스로 : gitk --all &.
  2. 를 실행하십시오 git rebase --onto a b f.
  3. 보도 F5gitk이 . 아무것도 변하지 않습니다. 그러나 HEAD표시가 없습니다 .
  4. 운영 git branch selection
  5. 보도 F5gitk이 . 커밋이있는 새 분기가 나타납니다.

이것은 것들을 명확히해야합니다 :

  • 커밋 a은 그룹의 새로운 루트 대상입니다.
  • 커밋 b은 그룹의 첫 번째 커밋 이전의 커밋입니다 (제외).
  • 커밋 f은 그룹의 마지막 커밋입니다 (포함).

그런 다음 분기 에서 git checkout feature && git reset --hard b커밋을 삭제할 c때까지 사용할 수 있습니다 .ffeature

이 답변 외에도 필자는 일반적으로 사용하는 데 도움이되는 다른 시나리오의 명령을 설명 하는 블로그 게시물 을 작성 했습니다.


2
mybranch (a..f commits)가 더 이상 필요하지 않은 경우 다음 git rebase --onto a b mybranch과 같이 단순화 할 수 있습니다.
Mr_and_Mrs_D

2
@Mr_and_Mrs_D 귀하의 의견에 감사드립니다. 내가 사용하는 생각 cacoo.com을 그림을 그립니다.
JJD

48

JB Rainsberger 및 sschaef의 의견을 적용하여 질문에 구체적으로 대답하려면 ...이 예에서 체리 픽 범위를 사용하려면 :

git checkout a
git cherry-pick b..f

또는

git checkout a
git cherry-pick c^..f

3
나는 git 2.7.0.windows.1커밋의 체리 선택 범위를 시도 할 때 모든 것이 정상이지만 git은 git cherry-pick --continue | --abort | --quit커밋 / 체리 선택을 다시 시도하기 전에 수행 해야 할 곳을 알려주지 않는다는 것을 알았 습니다. 따라서 커밋 범위를 선택 git cherry-pick --continue하면 주어진 범위에서 커밋 할 준비가 될 때마다 (충돌 해결 등) 실행해야합니다 .
kuskmen

정확히 똑같 았지만 치명적 임 : 'a..b'를 찾을 수 없음
Amit Karnik

나는 내가 틀렸다는 것을 모르지만 내 쪽에서 'git cherry-pick c ^ .. f'를 할 때 커밋 f는 포함되지만 커밋 c는 포함되지 않습니다. 그러나 모든 곳에서 읽을 때 c와 f를 포괄적으로 정의해야합니다. 아니면 내가 틀렸어?
사무엘

@ 사무엘 그래, 맞아. ^후의 C 실제로이 경우 B이다의 "C는 이전 커밋"를 의미한다. 이것이와 c^..f동의어 b..f입니다. 일을 시도 git log c^..f당신이 한 것과 정확히 같은, 당신은 f를 통해 커밋 C를 참조한다git log b..f
앤디

40

A, B, C, D, E, F, G, H, I, J 커밋에서 A, C, F, J와 같이 병합 할 선택적 개정이있는 경우 아래 명령을 사용하십시오.

자식 체리 픽 ACFJ


1
좋고 간단 함
spinup

21
git rev-list --reverse b..f | xargs -n 1 git cherry-pick

2
충돌이없는 경우 완벽하게 작동합니다. 그렇지 않은 경우 "rebase on"이 더 쉬울 수 있습니다. 중단 된 부분을 파악하고 나머지 패치를 다시 적용 할 필요가 없기 때문입니다.
Ruslan Kabalin

6
이 작업을 설명하는 의견을 추가하십시오
Mr_and_Mrs_D

7
아무도 설명하지 않았기 때문에 ... git rev-list는 브랜치 b에서 f (역전)까지 모든 개정을 인쇄하므로 각 행 (커밋 해시)이 순서대로 전달 될 때 각 행을 현재 git HEAD로 체리 선택합니다. 즉git cherry-pick {hash of c}; git cherry-pick {hash of d}; ...
coderatchet

8

커밋 ID에서 지점 끝까지 체리를 선택하려면 다음을 사용할 수 있습니다.

git cherry-pick commit_id^..branch_name


이것은 이미 답변의 일부입니다 stackoverflow.com/a/31640427/96823
tig

1
이 답변은 실제로 다르며 나에게 도움이되었습니다. 최종 커밋 SHA가 아닌 분기 이름을 지정합니다.
Subtletree 2016 년

7

언급 할 가치가있는 또 다른 변형 n은 분기에서 마지막 커밋 을 원하면 ~구문이 유용 할 수 있다는 것입니다.

git cherry-pick some-branch~4..some-branch

이 경우 위 명령은 분기에서 마지막 4 개의 커밋을 선택합니다 some-branch(분기 이름 대신 커밋 해시를 사용할 수도 있음)


1
매우 유용한 답변, 감사합니다! :)
Jacek Dziurdzikowski

3

실제로 가장 간단한 방법은 다음과 같습니다.

  1. 두 지점 간의 병합 기반을 기록하십시오. MERGE_BASE=$(git merge-base branch-a branch-b)
  2. 이전 분기를 새 분기로 빨리 감기 또는 리베이스
  3. 1 단계의 병합 기반에서 시작하여 결과 분기를 자체에 리베이스하고 원하지 않는 커밋을 수동으로 제거하십시오.

    git rebase ${SAVED_MERGE_BASE} -i
    

    또는 몇 가지 새로운 커밋이있는 경우 1 단계를 건너 뛰고 간단히

    git rebase HEAD^^^^^^^ -i
    

    첫 번째 단계에서는 ^병합 기반을 지나갈 만큼 충분히 사용 합니다.

대화식 리베이스에서 다음과 같은 것을 볼 수 있습니다.

pick 3139276 commit a
pick c1b421d commit b
pick 7204ee5 commit c
pick 6ae9419 commit d
pick 0152077 commit e
pick 2656623 commit f

그런 다음 줄 b와 원하는 다른 줄을 제거하십시오.


1
git format-patch --full-index --binary --stdout range... | git am -3

42
이 작업을 설명하는 의견을 추가하십시오
Mr_and_Mrs_D

0

다음은 체리 선택에 대한 소스 및 대상 분기와 커밋 수를 스크립트에 알려 주기만하면 여러 커밋을 연속적으로 체리 픽 선택하는 스크립트입니다.

https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81

브랜치에서 마스터로 체리 픽을 선택하려면 (현재 브랜치를 소스로 사용) :

./gcpl.sh -m

6.19.x 브랜치에서 마스터로 최신 5 개의 커밋을 선택하십시오.

./gcpl.sh -c 5 -s 6.19.x -t master

직접 힘내으로 그렇게 할 수있을 때이 스크립트가 필요하다 왜 ...?
code_dredd

타이핑이 적고 스크립트가 커밋을 자동으로 선택하므로 SHA별로 각 항목을 체리 선택하지 않아도됩니다. 어쨌든 YMMV.
nickboldt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.