Re: core.autocrlf=true causes `git apply` to fail on patch generated with `git diff-index HEAD --patch`
From: Anthony Sottile <hidden>
Date: 2017-08-01 20:59:16
Here's where I'm hitting the problem described: https://github.com/pre-commit/pre-commit/issues/570 Note that `git -c core.autocrlf=false` apply patch fixes this situation, but breaks others. Here's a testcase where `git -c core.autocrlf=false apply patch` causes a *different* patch failure:
#!/bin/bash
set -ex
rm -rf foo
git init foo
cd foo
git config --local core.autocrlf true
# Commit lf into repository
python3 -c 'open("foo", "wb").write(b"1\r\n2\r\n")'
git add foo
python3 -c 'open("foo", "wb").write(b"3\n4\n")'
# Generate a patch, check it out, restore it
git diff --ignore-submodules --binary --no-color --no-ext-diff > patch
python3 -c 'print(open("patch", "rb").read())'
git checkout -- .
git -c core.autocrlf=false apply patch
output:
+ rm -rf foo
+ git init foo
Initialized empty Git repository in /tmp/foo/.git/
+ cd foo
+ git config --local core.autocrlf true
+ python3 -c 'open("foo", "wb").write(b"1\r\n2\r\n")'
+ git add foo
+ python3 -c 'open("foo", "wb").write(b"3\n4\n")'
+ git diff --ignore-submodules --binary --no-color --no-ext-diff
warning: LF will be replaced by CRLF in foo.
The file will have its original line endings in your working directory.
+ python3 -c 'print(open("patch", "rb").read())'
b'diff --git a/foo b/foo\nindex 1191247..b944734 100644\n---
a/foo\n+++ b/foo\n@@ -1,2 +1,2 @@\n-1\n-2\n+3\n+4\n'
+ git checkout -- .
+ git -c core.autocrlf=false apply patch
error: patch failed: foo:1
My current workaround is: - try `git apply patch` - try `git -c core.autocrlf=false apply patch` which seems to work pretty well. Anthony On Tue, Aug 1, 2017 at 1:47 PM, Torsten Bögershausen [off-list ref] wrote:
On 08/01/2017 08:24 PM, Anthony Sottile wrote:quoted
Here's my minimal reproduction -- it's slightly far-fetched in that it involves*committing crlf* and then using `autocrlf=true` (commit lf, check out crlf).#!/bin/bash set -ex rm -rf foo git init foo cd foo # Commit crlf into repository git config --local core.autocrlf false python3 -c 'open("foo", "wb").write(b"1\r\n2\r\n")' git add foo git commit -m "Initial commit with crlf" # Change whitespace mode to autocrlf, "commit lf, checkout crlf" git config --local core.autocrlf true python3 -c 'open("foo", "wb").write(b"1\r\n2\r\n\r\n\r\n\r\n")' # Generate a patch, check it out, restore it git diff --ignore-submodules --binary --no-color --no-ext-diff > patch python3 -c 'print(open("patch", "rb").read())' git checkout -- . # I expect this to succeed, it fails git apply patchAnd here's the output:+ rm -rf foo + git init foo Initialized empty Git repository in/tmp/foo/.git/ + cd foo + git config --local core.autocrlf false + python3 -c 'open("foo", "wb").write(b"1\r\n2\r\n")' + git add foo + git commit -m 'Initial commit with crlf' [master (root-commit) 02d3246] Initial commit with crlf 1 file changed, 2 insertions(+) create mode 100644 foo + git config --local core.autocrlf true + python3 -c 'open("foo", "wb").write(b"1\r\n2\r\n\r\n\r\n\r\n")' + git diff --ignore-submodules --binary --no-color --no-ext-diff + python3 -c 'print(open("patch", "rb").read())' b'diff --git a/foo b/foo\nindex bd956ea..fbf7936 100644\n--- a/foo\n+++ b/foo\n@@ -1,2 +1,5 @@\n 1\r\n 2\r\n+\r\n+\r\n+\r\n' + git checkout -- . + git apply patch patch:8: trailing whitespace. patch:9: trailing whitespace. patch:10: trailing whitespace. error: patch failed: foo:1 error: foo: patch does not applyI also tried with `git apply --ignore-whitespace`, but this causes the line endings of the existing contents to be changed to*lf* (there may be two bugs here?) Thanks, AnthonyI can reproduce you test case here. The line git apply patch would succeed, if you temporally (for the runtime of the apply command) set core.autocrlf to false: git -c core.autocrlf=false apply patch So this seems to be a bug (in a corner case ?): Typically repos which had been commited with CRLF should be normalized, which means that the CRLF in the repo are replaced by LF. So you test script is a corner case, for which Git has not been designed, It seems as if "git apply" gets things wrong here. Especially, as the '\r' is not a whitespace as a white space. but part of the line ending. So in my understanding the "--ignore-whitespace" option shouldn't affect the line endings at all. Fixes are possible, does anyone have a clue, why the '\r' is handled like this in apply ? And out of interest: is this a real life problem ?