programing

다양한 커밋을 선택하여 다른 브랜치로 결합하려면 어떻게 해야 합니까?

elecom 2023. 4. 18. 21:44
반응형

다양한 커밋을 선택하여 다른 브랜치로 결합하려면 어떻게 해야 합니까?

다음과 같은 저장소 레이아웃이 있습니다.

  • 마스터 브랜치(실가동)
  • 통합
  • 일해

제가 달성하고 싶은 것은 작업 중인 브랜치에서 일련의 커밋을 체리픽하여 통합 브랜치로 통합하는 것입니다.저는 git을 처음 접하는데 어떻게 하면 저장소를 망치지 않고 정확하게 이것을 할 수 있는지 알 수 없습니다(마지하는 것이 아니라 하나의 조작으로 커밋 범위의 체리픽킹.이에 대한 조언이나 의견이 있나요?감사합니다!

다양한 커밋에 있어서 체리피킹실용적이지 않았다.

아래 Keith Kim에 의해 언급되었듯이 Git 1.7.2+는 다양한 커밋을 체리픽하는 기능을 도입하였습니다(그러나 향후 합병을 위해 체리픽의 결과에 대해 아직 인지할 필요가 있습니다).

cherry-pick cherry-pick의 법을 .
"cherry-pick A..B및 " " " "cherry-pick --stdin도 마찬가지입니다git revert은 더 제어를 ," "이것들은 더 좋은 순서 부여 제어를 지원하지 않습니다."rebase [-i]'이렇게 하면'

damian 코멘트 및 경고:

이러다'에서는 '이러다'라고 되어 .cherry-pick A..B" 형식은 보다 오래된 형식이어야 합니다.
잘못된 순서일 경우 명령이 자동으로 실패합니다.

(포함)을 통해 범위를 선택할 경우 (대신)가 됩니다.B..D를 참조해 주세요.
그림에서 "이전 커밋 범위에서 분기 생성?"을 참조하십시오.

Jubbs댓글에서 언급했듯이:

은 '하다'라고 합니다.B커밋이 .루트커밋이 ★★★★★★★★★★★★★★★★★★·unknown revision그렇지 않으면 에러가 발생합니다.

주의: Git 2.9.x/2.10 (2016년 3분기)부터는 고립된 브런치(빈 헤드)에서 직접 커밋 범위를 선택할 수 있습니다: "기존 브런치를 git에서 고립된 브런치로 만드는 방법"을 참조하십시오.


원답(2010년 1월)

A rebase --onto찰스 베일리가 여기서 설명한 처럼 통합 브랜치 위에 주어진 범위의 커밋을 반복하는 것이 좋습니다.
(또한 git rebase man 페이지에서 "여기서 어떤 브랜치에 기반한 토픽 브랜치를 다른 브랜치로 이식하는 방법"을 찾습니다).git rebase --onto)

현재 브런치가 연동되어 있는 경우:

# 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하는 첫 : 재생하는 첫 번째 커밋
  • 최고"integration)working (브랜치)

넋을 잃고tmp까지를 있다)integration이전에 가리키고 있었다)

이러한 커밋 중 하나가 재생될 때 충돌이 발생할 경우:

  • 해서 '어느 쪽인가를 git rebase --continue
  • "이러다"를실행하세요.git rebase --skip
  • git rebase --abort (이것, 이 것)을 원래대로 돌려놓는다.integrationtmp (브랜치)

후 ★★★rebase --onto,integration 브랜치의 커밋( "연동 브랜치의 마지막 커밋으로 .tmp + commits "branch + replayed commits")

또는 ★★★★★★★★★★★★★★★★★★★★★★★.rebase --onto여기서 설명한 바와 같이 후속 Marge에 영향이 있음을 잊지 마십시오.


순한 ' ' ''cherry-pick여기에서는 솔루션에 대해 설명합니다.다음과거기에는 다음과 같은 내용이 포함됩니다.

패치 어프로치를 사용하는 경우는, 「git format-patch|git am」및 「git cherry」를 선택할 수 있습니다.
★★★★★★★★★★★★★★★,git cherry-pick커밋만 , 1을 는,B through를 통해.D,이 .B^..D g로로 in in in로.

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

커밋의 를 「 필요가 경우는, 「이라고 하는 」이라고 하는「재연」을하도록 재촉할 필요가 있습니다.rebaseGit 특특 git git 。

git v1.7.2에서 체리 픽은 다양한 커밋을 받을 수 있습니다.

git cherry-pick을 배웠습니다(「커밋의 범위」).cherry-pick A..B ★★★★★★★★★★★★★★★★★」cherry-pick --stdin도 그랬습니다.git revert; 이것들은 보다 좋은 시퀀싱 제어를 지원하지 않습니다.rebase [-i]그래도요.

게이브 무타트가 말했듯이cherry-pick A..B " " " " 를 수 .A합니다)A~1..B 1에서는) .(git rebase는 git rebase가 됩니다).

2개의 브런치가 있다고 가정합니다.

"branchA" : 복사할 커밋이 포함되어 있습니다("commit"에서).A"에서 "커밋"B"

"branchB" : "branch"에서 커밋을 전송할 브랜치A"

1)

 git checkout <branchA>

2) "commit"의 ID를 취득한다.A" 및 "commit"B"

3)

git checkout <branchB>

4)

git cherry-pick <commitA>^..<commitB>

5) 충돌이 있을 경우 해결하고 입력

git cherry-pick --continue

체리 따기 작업을 계속하도록 하겠습니다.

실제로 지점을 병합하지 않으시겠습니까?작업 중인 브랜치에 원하지 않는 최근 커밋이 있는 경우 원하는 지점에 HEAD를 사용하여 새 브랜치를 만들 수 있습니다.

어떤 이유로든 다양한 커밋을 선택하고 싶다면 패치셋을 꺼내 새로운 통합 브랜치에 적용하는 것이 좋습니다.

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

이것은 기본적으로 git-rebase가 하고 있는 것이지만 게임을 할 필요는 없다. 해서 더하면 요.--3way로로 합니다.git-am통합이 필요한 경우.이 작업을 수행하는 디렉토리에 다른 *.patch 파일이 없는지 확인합니다.★★★★★★★★★★★★★★★...

git cherry-pick start_commit_sha_id^..end_commit_sha_id

★★git cherry-pick 3a7322ac^..7d7c123c

를 사용하고 있다고 가정합니다.branchA커밋을 선택하는 장소(범위에 대한 시작 및 종료 커밋 SHA가 지정되고 왼쪽 커밋 SHA가 오래된 경우)branchB포함)는branchA.

공식 문서에 제시된 예는 매우 유용합니다.

VonC의 코드를 짧은 bash 스크립트로 묶어서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같은 저장소에 두 개의 트리가 있지만 공유 조상이 없기 때문에 이 경우 도움이 됩니다.

git cherry-pick FIRST^..LAST는 단순한 시나리오에서만 기능합니다.

이미 통합된 픽의 자동 건너뛰기, 다이아몬드 머그 이식, 인터랙티브 컨트롤 등 일반적으로 편안함을 느끼면서 적절한 "통합 브랜치에 통합"을 달성하려면 리베이스(rebase)를 사용하는 것이 좋습니다.서의 한 했지만, 에는 주사위 의 의전, 의전, 의전, 의전 등이 .git branch -f 로스트메서드는 과 같습니다.다음은 스트레이트 로버스트 메서드입니다.

git rebase -i FIRST LAST~0 --onto integration
git rebase @ integration

-i대화식 제어가 가능합니다.~0는 LAST가 브랜치 이름일 경우 분리된 기본 재배치(다른 브랜치를 이동하지 않음)를 보장합니다.을 사용법 번째 는 "rebase"를 이동하기만 하면 .integration으로 중간 헤드로 합니다. - 하지 않습니다.새로운 커밋은 도입되지 않습니다.복합 구조를 병합 다이아몬드 등으로 다시 베이스화하려면 다음을 고려하십시오.--rebase-merges ★★★★★★★★★★★★★★★★★」--rebase-merges=rebase-cousins첫 번째 기본 재배치에서는.

저는 며칠 전에 Vonc의 아주 명확한 설명을 읽고 그것을 테스트했습니다.

나의 스텝

시작

  • ★★★devABCD E F GH J : A B C D E F G H I J
  • ★★★targetAB D : A B C D
  • i i i하 i i i i i i i i 。E 않다H

및하지 않고 dev_feature_wo_E_H

  • git checkout dev
  • git checkout -b dev_feature_wo_E_H
  • git rebase --interactive --rebase-merges --no-ff Ddrop의 의 앞E ★★★★★★★★★★★★★★★★★」H
  • , 및 '경합 해결', '계속'commit

를 하는 순서dev_feature_wo_E_H목표한 대로

  • git checkout target
  • git merge --no-ff --no-commit dev_feature_wo_E_H
  • , 및 '경합 해결', '계속'commit

몇 가지 코멘트

  • 해서cherry-pick

  • git cherry-pick하고 심플하지만 is워 is is is is is is

    • 중복된 커밋을 만듭니다.
    • 내가 때merge 2개의 커밋은 1, 2개입니다.cherry-pick좀더가 너무

위의 모든 옵션을 사용하면 병합 충돌을 해결하라는 메시지가 표시됩니다.팀에 대해 커밋된 변경 사항을 병합하는 경우 개발자로부터 병합 충돌을 해결하고 계속 진행하기가 어렵습니다.그러나 "git merge"는 한 번에 병합을 수행하지만 수정사항 범위를 인수로 전달할 수 없습니다.revs의 Marge 범위를 수행하려면 "marge diff" 및 "marge apply" 명령을 사용해야 합니다.패치 파일에 diff가 너무 많으면 git apply가 실패하기 때문에 파일별로 패치를 작성한 후 적용해야 합니다.스크립트는 소스 브랜치에서 삭제된 파일을 삭제할 수 없습니다.이는 드문 경우이므로 대상 분기에서 이러한 파일을 수동으로 삭제할 수 있습니다.패치를 적용할 수 없는 경우 "git apply"의 종료 상태는 0이 아닙니다.그러나 -3way 옵션을 사용하면 3방향 Marge로 돌아가기 때문에 이 장애에 대해 걱정할 필요가 없습니다.

다음은 스크립트입니다.

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"

또 하나의 옵션은 범위 전에 커밋을 전략과 병합한 후 해당 범위의 마지막 커밋(또는 마지막 커밋일 경우 분기)과 '정상' 병합하는 것입니다.따라서 기능 브랜치에 Marge되는 마스터 커밋은 2345 및 3456뿐이라고 가정합니다.

마스터:1234234534564567

기능 브랜치:

git merge - 우리의 4567git merge 2345

몇 가지 약속만 있고 체리픽을 하고 싶다면

git cherry-pick <commit> -n

그런 다음 새로운 커밋으로 만듭니다.

-n은 자동으로 커밋을 작성하는 것이 아니라 변경을 스테이징할 뿐이므로 커밋 내의 파일을 계속 선택하거나 변경할 수 있습니다.

병합이 어려울 수 있으며 패치를 만들고 수동으로 변경 사항을 적용하는 것만으로 쉽습니다.

  • start_commit에서 end_commit까지 패치 파일을 생성합니다.

    git diff <start_commit> <end_commit> > patch.diff

  • 지점을 체크 아웃하고 패치의 변경 내용을 수동으로 적용합니다.

언급URL : https://stackoverflow.com/questions/1994463/how-to-cherry-pick-a-range-of-commits-and-merge-them-into-another-branch

반응형