Skip to content

Git apply can convert LF file into CRLF when .gitattributes file is a part of a patch #3409

Open
@omirochn

Description

@omirochn
  • I was not able to find an open or closed issue matching what I'm seeing

Setup

  • Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
$ git --version --build-options

git version 2.33.0.windows.2
cpu: x86_64
built from commit: 8735530946cced809cc6cc4c2ca3b078cdb3dfc8
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
  • Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.17763.1]
  • What options did you set as part of the installation? Or did you choose the
    defaults?
# It's a portable version - no installation was done

# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"
> type "C:\Program Files (x86)\Git\etc\install-options.txt"
> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt"
$ cat /etc/install-options.txt

cat: /etc/install-options.txt: No such file or directory
  • Any other interesting things about your environment that might be related
    to the issue you're seeing?

** insert your response here **

Details

  • Which terminal/shell are you running Git from? e.g Bash/CMD/PowerShell/other

CMD then git-bash

Microsoft Windows [Version 10.0.17763.1]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\tmt>cd /d c:\temp\tst

c:\temp\tst>PortableGit-2.33.0.2-64-bit\bin\bash.exe
$ cat doit
git --version --build-options
rm -rf tst
mkdir tst
cd tst
mkdir repo.git
cd repo.git
git init --bare
cd ..
git clone repo.git 1
cd 1
mkdir cr lf
echo '* -text' > lf/.gitattributes
for d in *; do for b in {1..5}; do echo foo >> $d/foo; done; done
git add *
git commit -m init
git push
cd ../

git clone repo.git/ 2
cd 2
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done
for a in `find * -type f`; do echo '# dummy' >> $a; done
git commit -a -m dummy
echo ""
echo +++ After commit and before diff
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done
git diff --binary HEAD~ -- cr lf     > ../patch.with
git diff --binary HEAD~ -- cr lf/foo > ../patch.without
cd ..

echo ""
echo +++ Patches
for a in patch*; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done

git clone repo.git 3
cd 3

echo ""
echo +++ patch w/o .gitattributes
git reset --hard
echo +++ After reset and before patch
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done
git apply --binary ../patch.without
echo +++ After patch
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done

echo ""
echo +++ patch with .gitattributes
git reset --hard
echo +++ After reset and before patch
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done
git apply --binary ../patch.with
echo +++ After patch
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done

$ bash doit
git version 2.33.0.windows.2
cpu: x86_64
built from commit: 8735530946cced809cc6cc4c2ca3b078cdb3dfc8
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Initialized empty Git repository in C:/temp/tst/tst/repo.git/
Cloning into '1'...
warning: You appear to have cloned an empty repository.
done.
warning: LF will be replaced by CRLF in cr/foo.
The file will have its original line endings in your working directory
[master (root-commit) cc6174b] init
 3 files changed, 11 insertions(+)
 create mode 100644 cr/foo
 create mode 100644 lf/.gitattributes
 create mode 100644 lf/foo
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 360 bytes | 360.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To C:/temp/tst/tst/repo.git
 * [new branch]      master -> master
Cloning into '2'...
done.
CR cr/foo
LF lf/.gitattributes
LF lf/foo
warning: LF will be replaced by CRLF in cr/foo.
The file will have its original line endings in your working directory
[master 506cbe7] dummy
 3 files changed, 3 insertions(+)

+++ After commit and before diff
CR cr/foo
LF lf/.gitattributes
LF lf/foo

+++ Patches
CR patch.with
CR patch.without
Cloning into '3'...
done.

+++ patch w/o .gitattributes
HEAD is now at cc6174b init
+++ After reset and before patch
CR cr/foo
LF lf/.gitattributes
LF lf/foo
+++ After patch
CR cr/foo
LF lf/.gitattributes
LF lf/foo

+++ patch with .gitattributes
HEAD is now at cc6174b init
+++ After reset and before patch
CR cr/foo
LF lf/.gitattributes
LF lf/foo
+++ After patch
CR cr/foo
CR lf/.gitattributes
CR lf/foo
  • What did you expect to occur after running these commands?

As you can see above "git apply --binary" converts files into CRLF mode if .gitattributes file modification is included into a patch file

  • What actually happened instead?

Behavior should be consistent - "git apply --binary" should not convert files into CRLF mode because of unrelated change in .gitattributes file

  • If the problem was occurring with a specific repository, can you provide the
    URL to that repository to help us with testing?

The reproducer is from scratch.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions