다양한 커밋을 체리피킹하여 다른 브랜치에 병합하는 방법은?

다음과 같은 리포지토리 레이아웃이 있습니다:

  • 마스터 브랜치(프로덕션)
  • 통합
  • working

내가 달성하고 싶은 것은 작업 브랜치에서 다양한 커밋을 체리 피킹하여 통합 브랜치에 병합하는 것입니다. 나는 git을 처음 접했고 저장소를 엉망으로 만들지 않고이 작업 (병합이 아닌 한 번의 작업에서 커밋 범위의 체리 피킹)을 정확히 수행하는 방법을 알아낼 수 없습니다. 이에 대한 조언이나 생각이 있으신가요? 고마워요!

질문에 대한 의견 (1)
해결책

다양한 커밋에 대해 체리피킹을 통해 '델'을 고르는 것은 실용적이지 않았습니다.

아래 Keith Kim언급한 것처럼, Git 1.7.2+에는 다양한 커밋을 체리피킹하는 기능이 도입되었다(하지만 향후 병합 시 체리피킹의 결과에 대해서는 여전히 알고 있어야 한다).

다양한 커밋을 선택하는 방법을 배웠다. (예: &###cherry-pick A..B&## 및 &###cherry-pick --stdin&##), &##git revert&##도 마찬가지이지만, &###rebase [-i]&##가 가진 더 나은 시퀀싱 컨트롤을 지원하지 않는다.

데미안 코멘트 그리고 우리에게 경고합니다:

"'체리 선택 A..B'형식에서 AB보다 오래되어야합니다.
순서가 잘못되면 명령은 자동으로 실패합니다**.

'B'에서 'D'까지의 범위(포함)를 선택하려면 B^...D**가 됩니다.
예시로 을 참고한다.

Jubobs]7댓글에서 언급했듯이:

이것은 B가 루트 커밋이 아니라고 가정하며, 그렇지 않으면 알 수 없는 리비전 오류가 발생한다.

참고: Git 2.9.x/2.10(2016년 3분기)부터 고아 브랜치(빈 헤드)에서 직접 커밋 범위를 선택할 수 있다: 을 참고한다.


원래 답변 (2010년 1월)

찰스 베일리가 여기에 설명한 것처럼10 통합 브랜치 위에서 주어진 커밋 범위를 재생하는 rebase --onto가 더 좋을 것이다.
(또한, git rebase --onto의 실제 예제를 보려면 git rebase man page에서 을 찾아보십시오).

현재 브랜치가 통합 브랜치인 경우:

# Checkout a new temporary branch at the current location
git checkout -b tmp

# Move the integration branch to the head of the new patchset
git branch -f integration last_SHA-1_of_working_branch_range

# Rebase the patchset onto tmp, the old location of integration
git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration

그러면 그 사이의 모든 것이 재생됩니다:

  • 'first_SHA-1_of_working_branch_range'의 부모 뒤(따라서 ~1): 재생하려는 첫 번째 커밋.
  • '통합'까지(working 브랜치에서 재생하려는 마지막 커밋을 가리킴).

to &tmp&`(이전에통합`이 가리키던 위치를 가리킴).

이러한 커밋 중 하나를 재생할 때 충돌이 있는 경우:

  • 충돌을 해결하고 git rebase --continue를 실행한다.
  • 또는 이 패치를 건너뛰고 대신 git rebase --skip을 실행한다;

그 후 rebase --onto를 실행하면 통합 브랜치의 마지막 커밋(즉, tmp 브랜치 + 재생된 모든 커밋)에서 integration이 다시 돌아올 것이다.

체리 피킹 또는 rebase --onto를 사용하면 여기에 설명된과 같이 후속 병합에 영향을 미친다는 것을 잊지 마세요.


순수한 체리 피킹 솔루션은 여기에서 설명하며 다음과 같은 것을 포함합니다:

패치 접근 방식을 사용하려는 경우 , 및 가 옵션이다.
현재 git cherry-pick은 하나의 커밋만 허용하지만, B에서 D 범위의 커밋을 선택하려면 git 용어로 B^...D가 되므로 다음과 같이 해야 한다.

git rev-list --reverse --topo-order B^..D | while read rev 
do 
  git cherry-pick $rev || break 
done 

어쨌든 여러 커밋을 재생해야 할 때 재생이라는 단어는 Git의 리베이스 기능을 사용하도록 유도합니다.

해설 (17)

깃 (git) 다양한 커밋한 v1.7.2 체리 강조표시할 받아들일 수 있다.

깃 (git) ',' 체리 선택 &gt 다양한 커밋한 강조표시할 배웠다 (예를 들어 '체리 선택 A.B' 와 '체리 선택 - stdin'), 그렇게 리업으로 깃 (git) ',' 이러한 '리베이스 [- i]' 는 지원하지 못하는 괜찮게 순서 제어, 어쨌든요

해설 (2)

2 개 가지고 있는지 solaris.

&quot branchA"; . 커밋한 dm_ownerdm_owner 복사할지 () 의 &quot commita"; &quot 위해 commitB";

&quot branchB"; . 이 분기로의 커밋한 이전할 수 있도록 하려면 &quot branchA";

 git checkout 

2), commitA&quot &quot 내려받습니다 id; 및 &quot commitB";

git checkout 
git cherry-pick ^..
  1. 의 경우 충돌, pardiso it 및 유형
git cherry-pick --continue

체리 선택 계속 진행됩니다.

해설 (0)

브랜치를 실제로 병합하지 않으시겠어요? 작업 브랜치에 원하지 않는 최근 커밋이 있는 경우 원하는 지점에 HEAD를 사용하여 새 브랜치를 만들면 된다.

어떤 이유에서든 정말 다양한 커밋을 골라내고 싶다면 패치셋을 가져와서 새 통합 브랜치에 적용하는 것이 가장 좋은 방법이다:

git format-patch A..B
git checkout integration
git am *.patch

이것은 본질적으로 git-rebase가 하는 일이지만 게임을 할 필요는 없다. 병합이 필요한 경우 --3waygit-am에 추가할 수 있다. 지침을 그대로 따르는 경우 이 작업을 수행하는 디렉토리에 이미 다른 *.패치 파일이 없는지 확인하세요...

해설 (1)

실행하기 쉽도록 VonC의 코드를 짧은 배시 스크립트인 git-multi-cherry-pick으로 래핑했습니다:

#!/bin/bash

if [ -z $1 ]; then
    echo "Equivalent to running git-cherry-pick on each of the commits in the range specified.";
    echo "";
    echo "Usage:  $0 start^..end";
    echo "";
    exit 1;
fi

git rev-list --reverse --topo-order $1 | while read rev 
do 
  git cherry-pick $rev || break 
done 

저는 현재 타사 코드와 커스터마이징이 모두 동일한 svn 트렁크에 혼합된 프로젝트의 히스토리를 재구성할 때 이 방법을 사용하고 있습니다. 이제 핵심 타사 코드, 타사 모듈 및 커스터마이징을 각자의 git 브랜치로 분리하여 앞으로 커스터마이징을 더 잘 이해할 수 있도록 하고 있다. 같은 리포지토리에 두 개의 트리가 있지만 공유 조상이 없는 이 상황에서는 git-cherry-pick이 유용합니다.

해설 (0)

위의 모든 옵션을 병합해야 해결하십시오 충돌함 묻는 메시지가 나타납니다. 팀을 위해 커밋됩니다 병합합니다 경우 변경, 병합 충돌함 해결됨으로 충스러웠으니 개발자와 진행하십시오 얻기 힘들다. 그러나, git &quot merge&quot. 결합 한 샷을 할 수 없는 다양한 버전을 확장하지만 전달하십시오 인수로. 우리는 &quot diff&quot, 깃 (git) 을 사용할 수 있습니다. 깃 (git) 및 &quot apply"; 명령을 수행하기 위해 다양한 병합해야 회전 속도를 올린다. 나는 그 사실을 알고, git &quot apply&quot. 패치 파일이 diff 의 경우 페일오버됩니다 패치를 만들 수 있기 때문에, 우리는 너무 많은 파일 파일별 그리곤요 적용됩니다. 참고로 스크립트입니다 삭제된 파일을 삭제할 수 없게 소스 주장한다. 이는 드문 사례 등) 에서, 대상 분기로의 파일을 수동으로 삭제할 수 있습니다. 깃 (git) 의 종료 상태를 &quot apply"; 하지만 전혀 없는 경우, 3way 옵션을 사용할 경우 - 것이라고 할 수 없는 패치합니다 적용하십시오 폴백하는 don& 진실이며당신이 병합해야 3 way, t # 39 이 문제를 걱정할 필요가 없다.

다음은 스크립트입니다.

enter code here

  #!/bin/bash

    # This script will merge the diff between two git revisions to checked out branch
    # Make sure to cd to git source area and checkout the target branch
    # Make sure that checked out branch is clean run "git reset --hard HEAD"

    START=$1
    END=$2

    echo Start version: $START
    echo End version: $END

    mkdir -p ~/temp
    echo > /tmp/status
    #get files
    git --no-pager  diff  --name-only ${START}..${END} > ~/temp/files
    echo > ~/temp/error.log
    # merge every file
    for file in `cat  ~/temp/files`
    do
      git --no-pager diff --binary ${START}..${END} $file > ~/temp/git-diff
      if [ $? -ne 0 ]
      then
#      Diff usually fail if the file got deleted 
        echo Skipping the merge: git diff command failed for $file >> ~/temp/error.log
        echo Skipping the merge: git diff command failed for $file
        echo "STATUS: FAILED $file" >>  /tmp/status
        echo "STATUS: FAILED $file"
    # skip the merge for this file and continue the merge for others
        rm -f ~/temp/git-diff
        continue
      fi

      git apply  --ignore-space-change --ignore-whitespace  --3way --allow-binary-replacement ~/temp/git-diff

      if [ $? -ne 0 ]
       then
#  apply failed, but it will fall back to 3-way merge, you can ignore this failure
         echo "git apply command filed for $file"
       fi
       echo
       STATUS=`git status -s $file`

       if [ ! "$STATUS" ]
       then
#   status is null if the merged diffs are already present in the target file
         echo "STATUS:NOT_MERGED $file"
         echo "STATUS: NOT_MERGED $file$"  >>  /tmp/status
       else
#     3 way merge is successful
         echo STATUS: $STATUS
         echo "STATUS: $STATUS"  >>  /tmp/status
       fi
    done

    echo GIT merge failed for below listed files

    cat ~/temp/error.log

    echo "Git merge status per file is available in /tmp/status"
해설 (0)

또 다른 옵션을 볼 수 있는 전략을 병합하려면 우리 # 39, & # 39 를 전에 커밋합니다 후 maxvalorarray normal&. 마지막 커밋합니다 병합하고 그 범위 (또는 지사 때 가장 마지막에). 그래서 우리는 커밋한 2345 만 및 3456 병합되었습니다 피쳐보다 분기로의 마스터 할 수 있다. &lt pre>; 마스터: 1234년 2345 3456 4567 &lt /pre>; 피쳐 분기로의: &lt pre>; 우리 4567 병합해야 깃 (git) - s git 2345 병합해야 &lt /pre>;

해설 (0)