한 저장소에서 다른 저장소로 git 패치를 적용하는 방법은 무엇입니까?


80

두 개의 저장소가 있는데 하나는 라이브러리의 기본 저장소이고 다른 하나는 해당 라이브러리를 사용하는 프로젝트입니다.

하위 프로젝트를 수정하면 해당 패치를 업스트림에 쉽게 적용 할 수있는 방법이 필요합니다.

파일의 위치는 저장소마다 다릅니다.

  • 기본 저장소 : www.playdar.org/static/playdar.js
  • 계획: playlick.com/lib/playdar.js

나는 사용하여 시도 git format-patch -- lib/playdar.jsplaylick 프로젝트, 다음 git am주 playdar의 환매 특약에 있지만, 패치 파일에서 다른 파일 위치에 오류가 발생합니다.

주어진 파일에 대한 주어진 커밋의 패치를 다른 임의의 파일에 적용하는 쉬운 방법이 있습니까?

보너스 포인트의 경우 패치를 적용하려는 파일이 git 저장소에 없으면 어떻게됩니까?


답변:


117

수동 패치 파일을 편집하는 질문 또는 불가능 벗어나면,이 표준 옵션 (로모 수행 할 수 있습니다 git apply, git format-patch그리고 GNU patch).

  1. -p<n>n패치의 경로에서 선행 디렉토리를 제거 합니다.

  2. 처리 후 -p, --directory=<root>앞에 추가 root적용하기 전에 패치의 각 경로에 관한 것이다.

따라서 예를 들어 원래 있던 패치를에 static/playdar.js적용하려면 lib/playdar.js다음을 실행합니다.

$ cat patch_file | git am     \ 
          -p1                 \ # remove 1 leading directory ('static/')
         --directory='lib/'     # prepend 'lib/'

1
이 최고의 답변을 만들 기회가 있습니까? 이것은 패치 파일을 수동으로 편집하는 것보다 훨씬 쉽습니다.
weston

물론 @araqnid의 대답은 여전히 ​​알아두면 좋겠지 만 더 좋고 / 쉬운 대답입니다.
James Wheare

처음 시도한 후 디렉토리 조정과 관련이 있습니다 --directory. stackoverflow.com/questions/24121709/…
Ioannis Filippidis

38

에서 생성 된 패치 git format-patch는 단순히 텍스트 파일입니다. diff 헤더를 편집하여 다른 경로를 수정할 수 있습니다.

예를 들어 다음과 같이 생성되었을 것입니다.

diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js

당신이해야 할 모든 변화 lib/playdar.jsstatic/playdar.js다음 패치를 통해 실행git am"

패치는없는 사람들을위한 표준 GNU 패치 유틸리티 읽을 수 있어야 git---하지만 실행하지 않는 format-patch으로 -M,-C 그들에 대한 지원은 보편적하지 않기 때문에, 그 경우 생산 이름 바꾸기 패치 등의 옵션을 제공합니다.


1
나중에이 페이지를 다시 방문하는 중… 이것은 하위 모듈을 제안한 이전 "승자"보다 질문에 대한 더 나은 답변입니다.
James Wheare

4

두 프로젝트가 모두 git 프로젝트라고 가정하면 하위 모듈 이 당신에게 완벽하게 맞는 것 같습니다. 이를 통해 git 프로젝트가 다른 git 프로젝트에 동적으로 연결되어 본질적으로 다른 git repo 내에서 바로 git repo를 베이킹 할 수 있습니다.

즉, "프로젝트"의 하위 모듈로 "main repo"를 추가합니다. "메인 저장소"에서 새 항목을 커밋 / 푸시 할 때마다 git pull"프로젝트"로 돌아갑니다.


흠, 서브 모듈 문서를 읽었을 때, 이것이 가장 강력 할 수 있지만 "쉬운 방법"처럼 들리지는 않습니다. 내가 단지 포함하는 서브 모듈 만들어야 할 것 같습니다 playdar.js다음 (나는에서 다른 모든 싶지 않아 모두 다른 프로젝트에서 해당 포함 파일을 www.playdar.orgplaylick.com나는 지금 정직하게 수동의 패치 파일을 편집하기 위해 리조트 수도 프로젝트) . 또는 둘 사이에 붙여 넣기를 계속하십시오. 건배.
James Wheare

다음은이 질문에 걸림돌이되는 다른 사람을위한 명확하고 철저한 자습서와 git 하위 모듈 시작하기입니다. book.git-scm.com/5_submodules.html
James Wheare

2

Henrik의 답변 을 완료 하고 보너스 포인트 를 얻으려면

패치를 적용하려는 파일이 git 저장소에 없으면 어떻게합니까?

git 저장소에서 오는 패치에 대한 파일 후보의 디렉토리에 액세스 할 수 있다면 먼저 해당 디렉토리 / 파일 트리를 git 저장소 자체로 변환 할 수 있습니다! ( ' git init': git 저장소는 결국 루트 디렉토리 내의 .git 일뿐입니다).
그런 다음 해당 저장소를 기본 프로젝트의 하위 모듈로 설정합니다.


2

--relative옵션을 사용하여 format-patch추상화를 개선 할 수 있습니다 (패치가 생성 된 저장소에 대한 관련없는 세부 정보 숨기기).

[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'

오류 --3way방지를 위해 패치를 적용 할 때 필요한 옵션을 찾았습니다 does not exist in index. 마일리지가 다를 수 있습니다. 사용 --directory=(...)은 대상 경로가 저장소의 루트가 아닌 경우에만 필요합니다.

[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)

  • format-patch 'base'이후 현재 브랜치에 대한 커밋 당 하나의 패치 파일을 생성합니다.

  • --relative옵션에 대한 문서 가 일부 경우 누락 된 것처럼 보이지만 어쨌든 작동하는 것 같습니다 (버전 2.7.4 기준).



1

일시적으로 기본 저장소를 제거 (이름 변경) 할 수 있습니다.

cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.