git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Git apply can convert LF file into CRLF when .gitattributes file is a part of a patch
@ 2021-09-08  0:53 Mirochnik, Oleg V
  2021-09-11  6:43 ` Torsten =?unknown-8bit?Q?B=C3=B6gershausen?=
  0 siblings, 1 reply; 2+ messages in thread
From: Mirochnik, Oleg V @ 2021-09-08  0:53 UTC (permalink / raw)
  To: git@vger.kernel.org

Hi,

Originally the issue was reported in https://github.com/git-for-windows/git/issues/3409
But I was asked to report it in the mail list as the issue is not a Windows related.

As you can see below "git apply --binary" converts files into CRLF mode if .gitattributes file modification is included into a patch file.
IMO behavior should be consistent - "git apply --binary" should not convert files into CRLF mode because of unrelated change in .gitattributes file.

Steps:
$ cat doit
git --version --build-options
git config --global core.autocrlf true

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
git diff --binary HEAD~ --    lf     > ../patch.lf-only
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


echo ""
echo +++ patch no CR
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.lf-only
echo +++ After patch
for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done

git config --global core.autocrlf false

$ sh doit
git version 2.29.2
cpu: x86_64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
Initialized empty Git repository in /tmp/issue3409/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) fc793f1] 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 24 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 378 bytes | 378.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To /tmp/issue3409/tst/repo.git
 * [new branch]      master -> master
Cloning into '2'...
done.
CR cr/foo
LF lf/foo
LF lf/.gitattributes
warning: LF will be replaced by CRLF in cr/foo.
The file will have its original line endings in your working directory
[master 718534d] dummy
 3 files changed, 3 insertions(+)

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

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

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

+++ patch with .gitattributes
HEAD is now at fc793f1 init
+++ After reset and before patch
CR cr/foo
LF lf/foo
LF lf/.gitattributes
+++ After patch
CR cr/foo
CR lf/foo
CR lf/.gitattributes

+++ patch no CR
HEAD is now at fc793f1 init
+++ After reset and before patch
CR cr/foo
LF lf/foo
LF lf/.gitattributes
+++ After patch
CR cr/foo
LF lf/foo
LF lf/.gitattributes

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Git apply can convert LF file into CRLF when .gitattributes file is a part of a patch
  2021-09-08  0:53 Git apply can convert LF file into CRLF when .gitattributes file is a part of a patch Mirochnik, Oleg V
@ 2021-09-11  6:43 ` Torsten =?unknown-8bit?Q?B=C3=B6gershausen?=
  0 siblings, 0 replies; 2+ messages in thread
From: Torsten =?unknown-8bit?Q?B=C3=B6gershausen?= @ 2021-09-11  6:43 UTC (permalink / raw)
  To: Mirochnik, Oleg V; +Cc: git@vger.kernel.org

On Wed, Sep 08, 2021 at 12:53:42AM +0000, Mirochnik, Oleg V wrote:
> Hi,
>
> Originally the issue was reported in https://github.com/git-for-windows/git/issues/3409
> But I was asked to report it in the mail list as the issue is not a Windows related.
>
> As you can see below "git apply --binary" converts files into CRLF mode if .gitattributes file modification is included into a patch file.
> IMO behavior should be consistent - "git apply --binary" should not convert files into CRLF mode because of unrelated change in .gitattributes file.


It was probablty me who suggested to report this issue here on the mailing list.
Thanks for doing so.

I extracted your test script, run it on a Mac,
and it seems to give a different result then your run.

Just to quote the las lines:
+++ patch no CR
HEAD is now at a47b66d init
+++ After reset and before patch
LF cr/foo
LF lf/foo
LF lf/.gitattributes
+++ After patch
LF cr/foo
LF lf/foo
LF lf/.gitattributes
---------

Seeing this, I am unsure what is going on.
It may be an idea to convert the script into a real git test case,
and send it to the list.
There is a command
git ls-files --eol
to let Git report the line endings of files

Using
----------------
echo "this is what I expected" >expect &&
git ls-files --eol >actual &&
test_cmp expect actual
------------------

would allow everybody to see what is possible wrong.
And somebody may be willing to dig deeper - and if it
a bug, send a patch



>
> Steps:
> $ cat doit
> git --version --build-options
> git config --global core.autocrlf true
>
> 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
> git diff --binary HEAD~ --    lf     > ../patch.lf-only
> 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
>
>
> echo ""
> echo +++ patch no CR
> 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.lf-only
> echo +++ After patch
> for a in `find * -type f`; do echo `od -c $a | grep -q '\\r' && echo CR || echo LF` $a; done
>
> git config --global core.autocrlf false
>
> $ sh doit
> git version 2.29.2
> cpu: x86_64
> no commit associated with this build
> sizeof-long: 8
> sizeof-size_t: 8
> shell-path: /bin/sh
> Initialized empty Git repository in /tmp/issue3409/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) fc793f1] 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 24 threads
> Compressing objects: 100% (3/3), done.
> Writing objects: 100% (6/6), 378 bytes | 378.00 KiB/s, done.
> Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
> To /tmp/issue3409/tst/repo.git
>  * [new branch]      master -> master
> Cloning into '2'...
> done.
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes
> warning: LF will be replaced by CRLF in cr/foo.
> The file will have its original line endings in your working directory
> [master 718534d] dummy
>  3 files changed, 3 insertions(+)
>
> +++ After commit and before diff
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes
>
> +++ Patches
> CR patch.lf-only
> CR patch.with
> CR patch.without
> Cloning into '3'...
> done.
>
> +++ patch w/o .gitattributes
> HEAD is now at fc793f1 init
> +++ After reset and before patch
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes
> +++ After patch
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes
>
> +++ patch with .gitattributes
> HEAD is now at fc793f1 init
> +++ After reset and before patch
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes
> +++ After patch
> CR cr/foo
> CR lf/foo
> CR lf/.gitattributes
>
> +++ patch no CR
> HEAD is now at fc793f1 init
> +++ After reset and before patch
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes
> +++ After patch
> CR cr/foo
> LF lf/foo
> LF lf/.gitattributes

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-09-11  6:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-08  0:53 Git apply can convert LF file into CRLF when .gitattributes file is a part of a patch Mirochnik, Oleg V
2021-09-11  6:43 ` Torsten =?unknown-8bit?Q?B=C3=B6gershausen?=

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).