Search code examples
gitline-endingsgit-configgitattributes

Catch-22 with .gitattributes settings and initial clone of repo


Due to some issues with a 3rd party library I am using, I have a requirement to never auto-convert line-endings for my Git repository. It is a requirement that any code I push or pull has the same line endings stored in my workspace and on the remote (i.e. Both <CR><LF> and <LF> should remain unchanged at all times).

The following Git configuration allows this:

core.autocrlf false

To reduce environmental dependencies between developers, I have decided to use a .gitattributes file to configure this as described in this answer

* text=false

The problem I am having is in the initial clone of the repo on a new machine. Because the line ending configuration option is now in the repo itself, the initial clone uses the local environment's global line ending configuration. So, if a particular user's global configuration is like so:

core.autocrlf true

This means that a file with Unix-style line endings like this:

This file has<LF>
Unix style line endings.<LF>

Will end up in the workspace like so:

This file has<CR><LF>
Unix style line endings.<CR><LF>

It seems like a catch-22 situation, as it cannot apply the .gitattributes setting until it's cloned the repo. And at that stage its too late.

The obvious solution is to ensure that all users have the following global configuration value:

core.autocrlf false

But then, this defeats the purpose of using .gitattributes at all.

Is there a nice way around this?


Solution

  • A possible mitigation would be to version in your repo a script, which should be run by the developer after cloning the repo (as mentioned in the README of the same repo)

    That script would:

    • execute a git config --global core.autocrlf false
    • reset the index, triggering the eol normalization as I detailed here.

    You can couple that with a pre-receive hook on the server side (assuming you are pushing to a private repository hosting server) which would reject any push with the wrong eol.