로컬 Git 브랜치에서 원격 Git 브랜치로 하위 디렉토리의 변경 사항 만 병합 할 수 있습니까? 아니면 "모두 또는 아예"입니까?
예를 들면 다음과 같습니다.
branch-a
- content-1
- dir-1
- content-2
과
branch-b
- content-1
- dir-1
- `content-2
branch-a dir-1의 내용과 branch-b dir-1의 내용 만 병합하고 싶습니다.
로컬 Git 브랜치에서 원격 Git 브랜치로 하위 디렉토리의 변경 사항 만 병합 할 수 있습니까? 아니면 "모두 또는 아예"입니까?
예를 들면 다음과 같습니다.
branch-a
- content-1
- dir-1
- content-2
과
branch-b
- content-1
- dir-1
- `content-2
branch-a dir-1의 내용과 branch-b dir-1의 내용 만 병합하고 싶습니다.
답변:
SO 질문 " 선택 파일을 git-merge와 어떻게 병합합니까? "에 대한 대안으로 방금 git read-tree를 기반으로 전체 하위 디렉토리를 병합하는 데 더 적합 할 수있는 이 GitHub 스레드 를 찾았 습니다 .
- 내 저장소 =>
cookbooks
내 저장소 대상 디렉토리 =>cookbooks/cassandra
- 원격 저장소 =>
infochimps
병합하려는 원격 저장소 소스cookbooks/cassandra=>infochimps/cookbooks/cassandra
병합하는 데 사용한 명령은 다음과 같습니다.
- 저장소를 추가하고 가져옵니다.
git remote add -f infochimps git : //github.com/infochimps/cluster_chef.git
- 병합 수행
git merge --allow-unrelated-histories -s ours --no-commit infochimps / master
( 'ours'전략 ( -s ours) 을 사용하여 병합을 수행 하여 소스 분기의 변경 사항을 삭제합니다. 이는 infochimps/master대상 분기의 파일을 실제로 수정하지 않고 병합 된 사실을 기록합니다. )
- 만 병합
infochimps/cookbooks/cassandra으로cassandra
git read-tree --prefix = cassandra / -u infochimps / master : cookbooks / cassandra
이것은 소스 저장소 cookbooks/cassandra의 업스트림 브랜치 에서 필요한 소스 하위 디렉토리 즉 , 트리 만 읽습니다 .
점을 유의 대상 하위 디렉토리 이름도해야한다 cookbooks/cassandra, 또는 당신은 볼 것이다 :
fatal: Not a valid object name
- 변경 커밋
git commit -m 'merging in infochimps cassandra'
기괴합니다. [편집] — read-tree단계는 다음과 같이 실패 할 수 있습니다.
error: Entry 'infochimps/cookbooks/cassandra/README' overlaps with 'cookbooks/cassandra/README'. Cannot bind.
... 두 파일이 동일한 경우에도 . 도움이 될 수 있습니다.
git rm -r cassandra
git read-tree --prefix=cassandra/ -u infochimps/master:cookbooks/cassandra
그러나 물론, 이것이 원하는 것을 수동으로 확인하십시오.
<rev>:<path>예를 들어, HEAD:README, :README,master:./README
git read-tree단계는 나를 위해 실패error: Entry 'foo/bar/baz.php' overlaps with 'bar/baz.php'. Cannot bind.
overlaps with위에서 언급 한 오류가 동일한 파일 에서도 나타납니다 . 그게 얼마나 이상해?
infochimps/master병합 된 사실을 기록 하지만 실제로 대상 분기의 파일을 수정하지 않습니다. 다음 단계 git read-tree --prefix=cassandra에서 수정이 이루어 지기 때문 입니다. 최종 커밋은 실제 "병합"내용을 기록합니다.
내 예를 들어, 자신의 업스트림 버전을 반영하고 최신 코드로 가져 오는 분기 '소스'와 분기 '대상'이 있다고 가정합니다. 'source'브랜치에만 존재하는 newFeature라는 저장소의 하위 디렉토리를 원한다고 가정 해 보겠습니다.
git checkout destination
git checkout source newFeature/
git commit -am "Merged the new feature from source to destination branch."
git pull --rebase
git push
내가 본 다른 모든 것보다 훨씬 덜 복잡하며 여기 에서 찾을 수 있습니다 .
이것은 '실제 병합'이 아니므로 대상 브랜치에 newFeature에 대한 커밋 정보가없고 해당 하위 디렉터리의 파일에 대한 수정 만 있습니다. 그러나 아마도 나중에 전체 분기를 병합하거나 폐기 할 것이기 때문에 문제가되지 않을 수 있습니다.
Eclipse 의 포럼 스레드 에서 이것을 얻었 으며 매력처럼 작동했습니다.
git checkout source-branch
git checkout target-branch <directories-or-files-you-do-**NOT**-want>
git commit
git checkout target-branch
git merge source-branch
checkout폴더를 동일하게 만듭니다 => 차이점은 checkout폴더 해제 => merge차이점입니다. 유효한 전략입니다.
두 개의 분기가 있지만 분기 a 에서 분기 b 로 dir-1 의 기록 만 병합하려는 OP의 시나리오가 주어지면 다음과 같습니다.
# Make sure you are in the branch with the changes you want
git checkout branch-a
# Split the desired folder into its own temporary branch
# This replays all commits, so it could take a while
git subtree split -P dir-1 -b temp-branch
# Enter the branch where you want to merge the desired changes into
git checkout branch-b
# Merge the changes from the temporary branch
git subtree merge -P dir-1 temp-branch
# Handle any conflicts
git mergetool
# Commit
git commit -am "Merged dir-1 changes from branch-a"
# Delete temp-branch
git branch -d temp-branch
branch-a와 branch-b를 모두 포함하는 Git 리포지토리를 만듭니다.
git checkout branch-a
git diff branch-b dir-1 > a.diff
patch -R -p1 < a.diff
git cherry-pick원하는 커밋을 선택하고 이러한 커밋 만 병합하는 데 사용 합니다. 여기서 핵심 트릭은 이러한 커밋을 쉬운 방법으로 가져 오는 것입니다 (그러므로 수동으로 Git 로그를 확인하고 직접 입력하여 확인할 필요가 없습니다). 방법은 다음과 같습니다. 다음과 git log같이 커밋의 SHA-1 ID 를 인쇄하는 데 사용 합니다 .
git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>
'commit-a'는 병합 할 브랜치의 시작점 직전 커밋이고 'commit-b'는 병합 할 브랜치의 마지막 커밋입니다. '--reverse'는 이러한 커밋을 나중에 체리 피킹을 위해 역순으로 인쇄합니다.
그런 다음 다음과 같이하십시오.
git cherry-pick $(git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>)
간단하고 안정적인 두 단계입니다!
Two steps, simple and stable!전혀 간단 하지 않습니다 :)
git끔찍한 인터페이스와 수수께끼와 임의의 이름과 의미로 가득 찬 끔찍한 정신 모델을 가진 결함은 모두 켜져 있습니다.