이름과 경로가 다른 파일에 Git 패치를 적용하는 방법은 무엇입니까?


100

두 개의 저장소가 있습니다. 하나에서는 파일을 변경합니다 ./hello.test. 변경 사항을 커밋하고 해당 커밋에서 git format-patch -1 HEAD. 이제 hello.test와 동일한 내용을 가지고 있지만 다른 이름으로 다른 디렉토리에있는 파일을 포함하는 두 번째 저장소가 있습니다 : ./blue/red/hi.test. 앞서 언급 한 패치를 hi.test파일 에 적용하려면 어떻게해야 합니까? 나는 시도 git am --directory='blue/red' < patch_file했지만 물론 파일 이름이 동일하지 않다고 불평합니다 (Git가 신경 쓰지 않는다고 생각 했습니까?). 해당 특정 파일에 적용하기 위해 diff를 편집 할 수 있지만 명령 솔루션을 찾고 있습니다.


답변:


97

을 사용하여 패치를 git diff만든 다음 patch유틸리티를 사용하여 적용 할 수 있습니다. 그러면 diff를 적용 할 파일을 지정할 수 있습니다.

예를 들면 :

cd first-repo
git diff HEAD^ -- hello.test > ~/patch_file

cd ../second-repo
patch -p1 blue/red/hi.test ~/patch_file

7
아, 좋아, 그런 생각은 안 했어. 그러나 커밋 데이터 (날짜 및 시간, 커밋 작성자, 커밋 메시지)가 동일하게 유지되도록 Git 명령으로이를 수행 할 수있는 방법이 있습니까?
mart1n 2013 년

2
am또는로 할 수있는 작업이있을 apply수 있지만 찾을 수 없습니다. 변경 사항을 많이 복제하는 경우 하위 모듈을 사용하거나 선택한 언어가 코드를 공유하기 위해 제공하는 더 나은 솔루션이있을 수 있습니다 (예 : Ruby에서는 중복 코드를 gem으로 추출 할 수 있음).
georgebrock

1
이것은 실제로 문서와 관련이 있습니다 (소스 파일은 XML 임). 서브 모듈은 기존 인프라에서 강력한 사례를 만들어야하므로 실제로 옵션이 아닙니다.
mart1n 2013 년

52

수동 패치 편집이나 외부 스크립트를 포함하지 않는 간단한 솔루션이 있습니다.

첫 번째 저장소에서 (이것은 또한 커밋 범위를 내보낼 수 있습니다. -1하나의 커밋 만 선택하려는 경우 사용 ) :

git format-patch --relative <committish> --stdout > ~/patch

두 번째 저장소에서 :

git am --directory blue/red/ ~/patch

--relativein 을 사용하는 대신 git format-patch다른 해결책은 -p<n>in 옵션 을 사용 하여 유사한 질문 에 대한 답변 에서 언급했듯이 패치 경로에서 디렉토리 git am를 제거 n하는 입니다.

git format-patch --relative <committish>없이도 실행할 수 있으며 파일 --stdout집합을 생성 .patch합니다. 그런 다음 이러한 파일 git amgit am --directory blue/red/ path/to/*.patch.


9
이것은 여전히 ​​파일 이름이 동일하다는 사실에 의존합니다.
mart1n 2015

3
--directory옵션은 repo 루트에 상대적인 디렉토리의 전체 경로를 지정 해야하는 것으로 나타납니다. --directory=./repo의 하위 디렉토리에 chdir을 넣는 동안 같은 것은 작동하지 않습니다.
Reid

1
사용은 --3way에 도움이 does not exist in index:git am --3way --directory (relative-path) (patch)
브렌트 Bradburn에게

-k커밋 메시지의 첫 줄을 제거하지 않으려면 두 명령 모두에서 키를 사용하십시오 .
ruvim

사용하면 --3way"인덱스에 존재하지 않음"오류 (@nobar가 지적한대로)에 도움이 될뿐만 아니라 병합 충돌을 깔끔하게 처리 할 수 ​​있습니다. 충돌하는 파일을 그대로 두는 대신 해결할 수있는 충돌 블록이 추가됩니다.
Daniel Wolf

11

이 작업을 수행하는 스크립트로 내 질문에 답하기 : https://github.com/mprpic/apply-patch-to-file

패치 파일을 수동으로 수정하는 대신 사용자에게 대상 파일을 입력하라는 메시지를 표시하고 패치를 수정 한 다음 현재있는 리포지토리에 적용합니다.


5

@georgebrock의 답변을 바탕으로 내가 사용한 솔루션은 다음과 같습니다.

먼저 평소와 같이 패치 파일을 만듭니다 (예 :) git format-patch commitA..commitB.

그런 다음 대상 저장소가 깨끗한 지 확인하고 (변경되거나 추적되지 않은 파일이 없어야 함) 다음과 같은 패치를 적용합니다.

cd second-repo
git am ~/00*.patch

모든 패치 파일에 대해 "오류 : XYZ가 색인에 없습니다"와 같은 오류가 발생합니다. 이제이 패치 파일을 수동으로 적용 할 수 있습니다.

patch --directory blue/red < ~/0001-*.patch
git add -a
git am --continue

각 패치 파일에 대해이 세 단계를 수행해야합니다.

이것은 특별한 git format-patch명령 을 요구 하거나 패치 파일을 편집 하지 않고도 원래 커밋 메시지 등을 보존 합니다.


1
좋은 대답은 이것이 모든 종류의 "비표준"패치 조작을위한 최고의 기초라고 생각합니다. 3 단계로합니다. (1) 텍스트 작성 - git format-patch -1 commitA --stdout > thing.diff; (2) 내가 필요한 것을 할 때까지 패치 파일을 편집하십시오 . (3) git am --3way thing.diff 깔끔하게 적용되는 패치 부분을 수락 할 수있는 장점이있는 커밋 텍스트 , git그렇지 않은 부분에 대해서는의 표준 충돌 해결 프로세스를 사용합니다.
우리는 모든 모니카 있습니까

2

두 파일이 귀하의 상황에서 정확히 동일하다는 것을 알고 있으므로 패치가 성공할 가능성이 높습니다.

그러나 유사하지만 정확히 동일한 파일이 아닌 파일에 패치를 적용하거나 대화식 패치를 수행하려는 경우 3 방향 병합을 사용합니다.

당신이 파일을 수정 한 말 A,하자 나타낸다를 A~1이전 버전으로, 당신은 사이 DIFF을 적용 할 A~1A파일로 B.

3 방향 병합 도구를 엽니 다. 예를 들어 Beyond Compare에서 왼쪽 패널의 경로는 A, 중간 패널은 공통 조상이므로 경로는 A~1, 오른쪽 패널의 경로는 B입니다. 그런 다음 하단 패널에는 A~1to 의 diff A를 File 에 적용한 결과가 표시 B됩니다.

다음 그림은 아이디어를 보여줍니다.

여기에 이미지 설명 입력


0

참고 : 최근 Github에서 패치를 다운로드하여 로컬 파일에 적용하는 데 문제가있었습니다 (새 위치에서 "무시").

git am파일이 "인덱스에 없음"또는 "더러움"이기 때문에 패치를 적용하지 않습니다. 하지만 간단한 patch명령으로 패치를 적용 할 수 있다는 것을 알았습니다 . 패치 할 파일 이름을 묻는 메시지가 표시되었습니다.

어쨌든 일은 끝났습니다 ...

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