HOWTO · Git

Git 패치 오류 문제 해결

이 문서에서는 git 패치 적용과 관련된 몇 가지 일반적인 오류를 해결하는 방법에 대해 설명합니다.

이 페이지의 내용

Git 패치가 적용되지 않는 흔한 이유는 패치 형식과 명령이 맞지 않거나, 저장소 기준 커밋이 패치가 예상한 것과 다르거나, 패치의 문맥이 바뀌었기 때문입니다. 먼저 메일 형식 패치인지 일반 diff인지 확인하고, 대상 브랜치와 작업 트리를 살펴본 다음, 복구 방법을 선택하기 전에 적용 가능성을 점검하세요. git apply는 diff 패치를 처리하고, git am은 메일 패치를 처리하며 커밋을 만듭니다.

패치 형식과 사용할 Git 명령 식별하기

일반 diff 패치에는 보통 diff --git 행과 @@로 시작하는 파일 변경 구간이 들어 있습니다. git apply로 작업 트리에 적용하세요. git format-patch로 만든 패치는 커밋 메타데이터가 포함된 이메일 메시지이며, 일반적으로 git am으로 적용합니다. 이 명령은 커밋을 만들어 작성자와 커밋 메시지를 보존합니다. 두 명령은 서로 바꿔 쓸 수 없습니다. 파일 형식이 불분명하면 적용하기 전에 head로 첫 부분을 확인해 메일 헤더와 커밋 메타데이터가 있는지 살펴보세요.

이미 am 작업이 진행 중이라면 계속하기 전에 git status를 확인하세요. git am --continue는 현재 메일 패치를 해결한 뒤 작업을 이어가고, git am --abort는 작업을 중단해 시작 전 상태로 복원합니다. git am --skip은 현재 메일 패치를 건너뛰므로 해당 패치를 의도적으로 버릴 때만 사용하세요. 이 명령은 일반적으로 git apply에서 발생한 인덱스 오류를 무시하지 않습니다.

적용 전에 저장소와 패치 확인하기

먼저 git status --short --branch와 git branch --show-current를 실행하세요. 현재 브랜치가 의도한 대상인지 확인하고 추적 중인 파일, 스테이징된 변경 사항, 추적되지 않는 작업을 모두 파악하세요. 로컬 변경 사항을 덮어쓸 수 있는 상태라면 브랜치를 바꾸지 마세요. 먼저 커밋하거나 안전하게 스태시하는 등 변경 사항을 보존할 방법을 정하세요. 다른 커밋을 기준으로 만든 패치는 두 브랜치에 같은 파일이 있더라도 현재 브랜치에 맞지 않을 수 있습니다.

실행하기 전에 패치 내용을 살펴보세요. diff 패치 파일을 확인하는 명령으로 git diff --stat -- my_patch.patch를 사용할 수는 없습니다. 내용이나 영향을 받는 경로를 보려면 head, less 또는 git apply --stat my_patch.patch를 사용하세요. 그런 다음 git apply --check my_patch.patch를 실행합니다. 이 명령은 파일을 변경하지 않고 diff를 적용할 수 있는지 확인합니다. 패치가 의도한 변경인지, 이후 수정이 올바른지는 확인하지 않습니다. 메일 패치는 메시지를 살펴보고 일반 diff로 취급하지 말고 해당하는 git am 작업 흐름을 따르세요.

Git이 설치된 셸에서 다음 독립 실행 예제를 실행할 수 있습니다. 임시 저장소를 만들고 diff를 생성한 뒤, 원래 파일을 복원하고 같은 기준 상태에 diff를 적용합니다:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

set -eu
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
repo="$tmp/repo"
mkdir "$repo"
git -C "$repo" init -q
git -C "$repo" config user.name Example
git -C "$repo" config user.email example@example.com
printf 'first line
' > "$repo/note.txt"
git -C "$repo" add note.txt
git -C "$repo" commit -qm 'Add note'
printf 'first line
second line
' > "$repo/note.txt"
git -C "$repo" diff > "$tmp/change.patch"
git -C "$repo" checkout -- note.txt
git -C "$repo" apply --check "$tmp/change.patch"
git -C "$repo" apply "$tmp/change.patch"
printf 'Applied content: '
cat "$repo/note.txt"

예제에서 git apply --check는 사전 점검이고, 그 다음 git apply가 실제 변경을 수행합니다. 예제의 명령과 출력은 정본 그대로 유지되어 있으며, 출력에 포함된 사용자 표시 문자열은 영어로 남을 수 있습니다. 자신의 저장소에서는 생성된 diff 경로를 제공받은 패치 경로로 바꾸고, 스테이징하기 전에 git status를 다시 확인하세요.

흔한 Git 패치 오류 진단하기

patch does not apply 오류가 나거나 일부 변경 구간 적용에 실패했다면 Git이 대상 파일에서 예상한 문맥을 찾지 못한 것입니다. 패치가 다른 커밋을 기준으로 만들어졌거나, 해당 줄이 수정되었거나, 공백이 다를 수 있습니다. 변경 구간 주변의 줄을 현재 파일과 비교하고 기준 커밋이 맞는지 확인하세요. --ignore-space-change나 --ignore-whitespace 같은 공백 설정은 공백만 다른 경우에 도움이 될 수 있지만, 변경된 로직이나 누락된 파일, 무관한 내용의 충돌은 해결하지 못합니다.

file already exists in index 메시지는 인덱스 또는 경로의 충돌을 가리키지만, 메시지만으로 패치에서 왜 그런 문제가 생겼는지는 알 수 없습니다. git status를 확인하고 git ls-files --stage -- path/to/file로 해당 경로를 살펴본 다음 패치의 변경 구간을 읽으세요. 변경 사항이 이미 스테이징되었는지, 패치가 이미 추적 중인 경로를 추가하려는지, 또는 패치가 다른 저장소 기준으로 만들어졌는지 판단하세요. 의도한 상태를 파악하기 전에는 인덱스를 초기화하거나 파일을 삭제하지 마세요.

error in file 메시지도 원인 하나를 특정하기에는 너무 포괄적입니다. 앞뒤의 Git 출력과 해당 파일, 관련 패치 변경 구간을 살펴보고 파일 경로의 철자와 대소문자가 예상대로인지 확인하세요. 패치가 손상되었다고 단정하지 말고, 더 구체적인 오류 내용을 바탕으로 수정 방법을 선택하세요.

실패한 패치의 복구 방법 선택하기

git apply --check에서 문맥 불일치가 보고되면 먼저 대상의 기준 상태를 다시 파악하세요. 올바른 브랜치나 커밋이 필요할 수도 있고, 현재 파일에 맞게 패치를 수동으로 조정해야 할 수도 있습니다. 무작정 브랜치를 바꾸지 마세요. 대상을 변경하기 전에 로컬 변경 사항을 검토하고 보존하세요. 의도한 기준 상태를 준비한 뒤 점검을 다시 실행합니다.

서로 독립적인 변경 구간 중 적용 가능한 것만 Git이 적용하도록 하려면 git apply --reject my_patch.patch를 사용할 수 있습니다. 적용 가능한 변경 구간을 반영하고, 거부된 변경 구간은 .rej 파일에 기록합니다. 이는 부분 적용입니다. 영향을 받은 모든 원본 파일과 .rej 파일을 살펴본 뒤 거부된 변경 사항을 수동으로 반영하거나 제외하세요. 이 명령이 거부된 내용을 해결하거나 패치 전체를 완성해 주지는 않습니다. 모든 변경을 한 번에 적용하려면 점검이 성공한 다음 일반 git apply를 사용하세요.

사용할 수 있는 기준 정보가 있는 패치라면 git apply --3way my_patch.patch로 Git에 3방향 병합을 요청할 수 있습니다. 필요한 기준 블롭을 사용할 수 없으면 명령이 실패할 수 있습니다. 3방향 적용이 성공해도 충돌 표시가 남아 수동으로 해결해야 할 수 있습니다. 문맥이 바뀐 경우 시도해 볼 방법이지, 모든 상황에 통하는 대안은 아닙니다. 공백 옵션은 별개이므로 공백 차이가 문제라고 확인된 경우에만 사용하세요.

충돌 해결 및 결과 확인하기

복구 방법을 사용한 뒤에는 git status --short와 git diff --로 변경된 파일과 스테이징되지 않은 내용을 확인하세요. --reject로 패치를 적용했다면 .rej 파일을 찾아 각 거부된 변경 구간을 현재 원본과 비교하세요. 3방향 적용 후 충돌이 남았다면 충돌 표시를 검색하고, 각 파일을 의도한 최종 내용으로 수정한 뒤 표시가 남아 있지 않은지 확인하세요. 메일 패치 작업이라면 git status에 표시된 git am 상태를 살펴보고 적절히 계속하거나 중단하세요.

스테이징하기 전에 git diff --check로 전체 diff의 공백 문제를 확인하고, git diff로 실제 변경 내용을 검토하세요. 이미 스테이징된 내용이 있다면 git diff --cached도 살펴보세요. 결과 파일에 의도한 변경이 들어 있고 관련 없는 로컬 작업이 그대로 남아 있는지 확인하세요. 검토를 마친 뒤에만 스테이징하거나 커밋할지 결정하세요. git log로 git am이 새로 만든 커밋을 확인할 수 있지만 작업 트리의 모든 변경 사항을 보여 주지는 않으므로, 전체 결과를 검증할 때는 상태와 diff 출력을 함께 사용하세요.