3

If a .gitattributes file is added to given directory, with exactly the following content:

*.txt    text

Is there any possible way that a new file or a previously normalized file (e.g. all LF line-endings) could be committed to that directory and not be normalized? I.e., is there any possible way that new CRLF line endings could be introduced into the repository after enabling .gitattributes with text mode specified?

To paraphrase again, is this .gitattributes file an absolutely foolproof way to prevent new CRLF lines from being committed to *.txt files in the directory that contains the .gitattributes file? I want to convince my colleagues that the .gitattributes file is entirely sufficient, and that further measures to exclude CRLFs (e.g. a server-side hook) are unnecessary.

An answer should either confirm that it is impossible to override the line-ending behavior specified by .gitattributes, or provide a counterexample explaining how one could circumvent the .gitattributes file and sneak in some CRLF line endings.

kostmo
  • 6,222
  • 4
  • 40
  • 51
  • Note to self: here is another case of trying not circumvent gitattributes eol rules: http://stackoverflow.com/q/17123998/6309 – VonC Jun 18 '13 at 18:48

2 Answers2

2

Not easily through gitattributes, since negative pattern are forbidden.

There is actually a patch being proposed this days (March 2013) to Make !pattern in .gitattributes non-fatal.

So you need to put a global rule like *.txt only in .gitattributes files present in sub-directories where you known you won't need CRLF.

And reserve more fine-grained text rules in .gitattributes present in directories with mixed content.


kostmo mentions in the comments the EGit bug 421364:

Until this is implemented, I recommend this setup:

  1. For each Eclipse project, go to Properties > Resource and change "New text file line delimiter" to Other: Unix. Commit the resulting .settings/org.eclipse.core.runtime.prefs files.
  2. Don't configure any .gitattributes or "core.autocrlf" for Git.
    This means that files will have the same line endings in the working directory as in the repository. Git and EGit will not convert any file contents.

With 1., all new files that are created in Eclipse will have correct (LF) line endings, even when created by a user on Windows.

For files that are already in your repository with CRLF, you can fix them and commit the result. I recommend using dos2unix or fromdos on the command line.

Note: that issue (bug 421364) has just now (March 25th, 2014) been requalified as duplicate of bug 342372 by Lars Vogel.

So, the support of .gitattributes by JGit is "assigned", but its implementation is still in progress.

The implementation is being reviewed (January 2015):

Core classes to parse and process .gitattributes files including support for reading attributes in WorkingTreeIterator and the dirCacheIterator.

  • "review 35377" Adds the git attributes computation on the treewalk

Adds the getAttributes feature to the tree walk.
The computation of attributes needs to be done by the TreeWalk since it needs both a WorkingTreeIterator and a DirCacheIterator.


Update August 2018: the bug mentioned above (bug 342372) depends on JGit bug 537410, which just got resolved.
"JGit rebase and stash dont preserve line endings"

The problem is that the ResolveMerger during processEntry() does not remember the CheckoutMetadata (in which JGit stores filters and eol-attributes) for the files and then checks them out in checkout() ignoring any attributes or filters.

ResolveMerger.cleanUp() has the same problem.

JGit commit 4027c5c (from review 127290) should fix that.
THanks to Thomas Wolf an active contributor to JGit.

That gives hope for EGit:

EGit in general leaves all this eol handling in staging/merging/checkout to JGit.
The only places where EGit has to care about it is in the compare framework when it has to read index entries itself, and there it already properly handles CheckoutMetadata.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • OK, so to paraphrase my question, is the above `.gitattributes` file an *absolutely foolproof* way to prevent new CRLF lines from being committed to `*.txt` files in the directory that contains the `.gitattributes` file? I want to convince my colleagues that the `.gitattributes` file is sufficient, and that further measures to exclude CRLFs (e.g. a server-side hook) are unnecessary. – kostmo Jun 18 '13 at 07:58
  • @kostmo yes, as long as you keep config `core.autocrlf` to `false` (http://stackoverflow.com/a/2016763/6309): you can define `eol` rules in the `.gitattributes`: see http://stackoverflow.com/a/12702862/6309 – VonC Jun 18 '13 at 08:24
  • Are you saying that if `core.autocrlf` was `true`, a user could produce a commit that defies the `.gitattributes` setting? – kostmo Jun 18 '13 at 18:57
  • Nope: gitattributes rules have precendence over a global config like core.autocrlf: see http://git-scm.com/docs/gitattributes: "The `core.eol` configuration variable controls which line endings Git will use for normalized files in your working directory; the default is to use the native line ending for your platform, or `CRLF` if `core.autocrlf` is set. ... If the `text` attribute is unspecified, Git uses the `core.autocrlf` configuration variable to determine if the file should be converted." – VonC Jun 18 '13 at 19:04
  • Somehow some CRLF's got into our repository some time after setting the offending files to be "text" format in the `.gitattributes` file and normalizing the line endings of all of those files. My suspicion is that JGit/EGit (Eclipse's built-in Git client) is not respecting the same rules that the native Git command-line client uses. Since the enforcement is only client-side, it seems that it is possible to circumvent `.gitattributes` normalization after all. – kostmo Dec 24 '13 at 00:37
  • [Here is the EGit bug](https://bugs.eclipse.org/bugs/show_bug.cgi?id=421364) directed toward `.gitattributes` line ending support. – kostmo Dec 28 '13 at 00:42
  • @kostmo interesting, thank you. I have included that reference in the answer for more visibility. – VonC Dec 28 '13 at 07:36
1

To paraphrase again, is this .gitattributes file an absolutely foolproof way

No. Git has a lot of conveniences to make the usual tasks easy and put speedbumps in the way of questionable things, but it won't limit your control over your own repo.

I want to convince my colleagues that the .gitattributes file is entirely sufficient, and that further measures to exclude CRLFs (e.g. a server-side hook) are unnecessary.

They are necessary. Nobody can control what others do in their own repos.

git update-index --cacheinfo \
        100644,`git hash-object -w --no-filters path/to/file`,path/to/file

From the git hash-object docs

--no-filters
Hash the contents as is, ignoring any input filter that would have been chosen by the attributes mechanism, including the end-of-line conversion. If the file is read from standard input then this is always implied, unless the --path option is given.

jthill
  • 55,082
  • 5
  • 77
  • 137