Git commits wrong newlines when using .gitattributes - windows

I was having an issue where merge conflicts resulted in the entire file being a conflict. This ended up being that the local file's newlines all became unix-style newlines (LF) at the time of merge (before merge both development and feature branch had CRLF newlines when checked out).
If I ran
git rm --cached -r .
git add -A
no changes would show up with git status. But when I deleted the .gitattributes file and did another remove all / add all it resulted in certain files being updated with different new lines. For example for a 100 line file it would say 100 lines deleted, 100 lines added. After doing this to both branches the merges were fine.
.gitconfig autocrlf = true was set and .gitattributes file only had these lines. I would think the below lines would only affect merging strategry.
*.csproj -text merge=union
*.sln -text merge=union
Why would this .gitattributes change how new lines are committed?
Also with autocrlf set to true I'm not sure why the merge would be comparing LF's vs CRLF's unless maybe something in the .gitattributes was overriding it.
From https://help.github.com/articles/dealing-with-line-endings
Optionally, you can configure the way Git manages line endings on a
per-repository basis by configuring a special .gitattributes file.
This file is committed into the repository and overrides an
individual's core.autocrlf setting, ensuring consistent behavior for
all users, regardless of their Git settings. The advantage of a
.gitattributes file is that your line configurations are associated
with your repository
This makes it clear that .gitattributes is capable of overriding autocrlf, but there are no settings in it that tell it to do any eol conversion. Maybe there is some default that is implicitly used.

I realise this is an old question, but the answer might be useful for someone having a related issue.
The gitattributes file specifies -text for *.csproj and *.sln files. This means that for those files no EOL conversion should be done.
On the other hand, you also used the configuration autocrlf = true. This setting means: store the files with LF line endings in the Git repository and store the files with native line endings in the working directory.
So: before adding the gitattributes file, the *.csproj and *.sln files are stored with LF line endings in the Git repo, because of the autocrlf setting. After adding the gitattributes file and checking out those files in the working directory, no EOL conversion is done, and those files end up with LF line endings in the working directory.

Related

Git checkout files with LF line endings

PSR-12 for PHP and Airbnb's ESLint config for React requires LF line endings over CRLF. I see in the ESLint docs that they recommend adding a .gitattributes file with content similar to this:
*.js text eol=lf
I checked the Git documentation and it mentions that using eol can make paths be considered dirty. What is meant by this? I also notice there's mentions of core.safecrlf later in the docs, so can these types of conversions cause irreversible problems?
Will I also need to set core.autocrlf to false so that .gitattributes takes effect?
When you set a file in text mode in Git, that tells Git that you want it to perform end-of-line conversion. That means that Git will always write the file into its internal storage with LF endings, and then check out the endings that are specified, whether that's due to .gitattributes or various configuration options.
If, however, the repository already contains files with CRLF line endings checked in, then setting the eol option will cause the file to be checked into the repository with LF endings, as mentioned above. This will make Git think the file is modified, which it is. That's what's meant by making "the paths to be considered dirty."
The easiest way to solve this problem is to add the entries to .gitattributes, add the .gitattributes file, and then run git add --renormalize . and then commit. That way, any files which had CRLF endings will be converted to LF endings in the repository.
You don't also need to set core.autocrlf in addition. That behavior is overridden by the .gitattributes file.

Where should I put .gitattributes file so that PyCharm reads it (Windows 10)?

I have a simple .gitattributes file with (only) the following in it:
* text eol=lf
in my user home directory on Windows 10. It seems that PyCharm ignores it when I pull origin/master git repository, namely the newly checked out files always have CRLF endings.
Where should I put the file in order for it to be read by PyCharm? Alternatively, is there any other way to make PyCharm always check out files with LF line endings?
The .gitattributes file is parsed by git not PyCharm.
Where should I put the file ... ?
From the git docs [emphasis mine]:
When deciding what attributes are assigned to a path, Git consults $GIT_DIR/info/attributes file (which has the highest precedence), .gitattributes file in the same directory as the path in question, and its parent directories up to the toplevel of the work tree (the further the directory that contains .gitattributes is from the path in question, the lower its precedence). Finally global and system-wide files are considered (they have the lowest precedence).
Attributes which should be version-controlled and distributed to other repositories (i.e., attributes of interest to all users) should go into .gitattributes files.
If you think your attributes are ignored, you can double check your current configuration with git-check-attr, for example:
git check-attr eol *
git check-attr --all <some_path>
The .gitattributes file should be stored at the root of your git repository, close to the .gitignore or the .gitmodules files (if they exists), or at least close to the .git folder.

.gitattributes don't work properly on mac and windows

On my project i use computers with different OS, one is Mac second is with windows. When I use git every change is shown as whole document change. The reason is different end-of-line in these two OS. I read this https://help.github.com/articles/dealing-with-line-endings/ and made a .gitattributes file in the root folder but the problem still exists. This is my .gitattributes file:
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.css text
*.html text
*.js text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
I have no idea why it's not working because I was try a lot of configurations of this file before.
The .gitattributes file should be added with the first commit. If you add it a few commits in, you need to normalize all the existing files explicitly.
$ rm .git/index # Remove the index to force Git to
$ git reset # re-scan the working directory
$ git status # Show files that will be normalized
$ git add -u
$ git commit -m "Introduce end-of-line normalization"
See https://git-scm.com/docs/gitattributes
If .gitattributes file was not added with the first commit, the following should be performed to apply attributes locally:
Go to the root of the repository
Check status:
git status
If it says "nothing to commit, working tree clean", perform:
git rm --cached -r .
git reset --hard
The answer is based on https://dev.to/deadlybyte/please-add-gitattributes-to-your-git-repository-1jld

Git core.safecrlf different behavior on files with same line endings

I have Windows machine with VS project and I use both Visual Studio and tools from Cygwin environment including Git. Sometimes I get different line endings in files after editing. I want simple solution to check files' line ending consistency before they go to the repo. Git's core.safecrlf is the right thing I suppose.
Now I have a strange behavior:
Files A and B with following parameters:
$file A
A: HTML document, UTF-8 Unicode text, with CRLF line terminators
$file B
B: HTML document, UTF-8 Unicode (with BOM) text, with CRLF line terminators
File A is already in repo, file B is new one. Note, both have CRLF line endings. Now try to stage them, core.safecrlf is true.
$git add A # ok
$git add B # fails
fatal: CRLF would be replaced by LF in B.
Am using core.safecrlf correctly? Or maybe I need to write hook to check files?
Notes:
tried with different file encodings (with and without BOM), no difference.
there's related core.autocrlf feature in Git, added it to tags (Stackoverflow has no tag for core.safecrlf)
git version 1.8.5.rc1.17.g0ecd94d (compiled from sources under Cygwin)
EDIT #1: checked out core.autocrlf - it was input. Changed to false, now I can add both files. Why?
According to your later edit core.autocrlf = input was the original setting. With this setting CRLF is converted to LF when checked in to the repository and is kept that way when checked out. This means a non Unix line endings aware editor like Notepad would mess up the appearance of a checked out version of the file. It would be one giant long line.
FWIW core.autocrlf = input is the preferred setting on Unix systems and using the default cygwin build probably set it that way. In Windows the recommended settings is core.autocrlf = true which is what msysgit recommends
core.safecrlf = true aborts the conversion of a file if checking out the file will result in a changed and possibly damaged file which would be the case if Notepad was the editor. This is why file B was aborted because it would be messed up in an editor like Notepad. The difference between core.SAFEcrlf and core.AUTOcrlf should be noted. It is one of the eyes glazing over issues in understanding git line endings
core.autocrlf = false is don't care mode. It will check in and check out the files exactly as they are, which is why the commits now work. This is not very smart and is not recommended because it causes problems if the files are edited on both Windows and Unix systems and also if another users core.autocrlf settings differ and change the file endings.
My own preference is to set core.autocrlf to input on Windows if all the Windows editors and other text file processing tools on the project are Unix line ending aware, otherwise set it to core.autocrlf = true for Windows and core.autocrlf = input for Unix. In any case this approach is outmoded by the superior method of the .gitattributes file.
The .gitattributes file method processes files based on the file name and is maintained in all users environments as it is checked out into the working directory like .gitignore. The settings for as many file names and types as are relevant to your project should be added to .gitattributes. Your configuration then falls back onto the local core.autocrlf and core.safecrlf settings if the file name is not matched in .gitattributes. Adding * text=auto at the top of .gitattributes will cause git to do a best guess on file names which are not matched by the later .gitattributes settings.
This web page, Mind the End of Your Line helped me understand the issue better. You might read for more background on the issue.
The CR LF line ending choices are not that easy to understand. There are two places for the descriptions in that it is covered both in Git-attributes and Git-config manuals.
Initially there were the autocrlf settings, and then there were the newer versions which have some potential incompatibilities (i.e. do unexpected things as you indicate).
I tend to set the eol=LF, which makes all text files be committed as LF line endings (you can set attributes as to which files are considered text) and then add the safecrlf for doing a round trip check.

How to solve the "Wall of Pink" in Github for Windows?

I'm using Github for Windows on Windows 7, sometimes it shows a wall of pink of some file, even that file has not been modified at all (as the following pic shows). I found an article talking about this, but I don't find a good solution.
Is there a way to make Github for windows work correctly rather than change the CRLF chars to LF in my file? I like CRLF....
I like CRLF....
Everybody does on Windows ;-)
Except that Git prefers to internally store textual content with LF line ending delimiters.
However, you can have both: CRLF in your working directory and LF in the git object database. There's a git built-in mechanism that facilitates that for you.
Indeed, as stated in Scott Hanselman's post,
[...]you can do what GitHub for Windows suggests with text=auto (and create a .gitattributes file per repo containing the following lines).
# Auto detect text files and perform LF normalization
* text=auto
What's text=auto do?
This ensures that all files that git considers to be text will have
normalized (LF) line endings in the repository. 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.
Another very useful piece of content is Tim Clem's post Mind the End of Your Line. This brilliantly explains the whys and hows of Git line endings.
Update
nulltoken, I have .gitattributes in my project folder, and it has text=auto, but the github client just show me pink walls again and again.
Following your comment above, below some additional points to consider. This will require you to switch to command line in order to run some git commands.
Make sure that the .gitattributes file is committed and not only lies in your project folder.
In order not to loose anything, make sure that you do not have any pending changes (eg. running git status should output something like nothing to commit, working directory clean)
Run git checkout-index --force *. This will recreate all your files in your working directory, taking into account the directives in the .gitattributes file. Once this is done, every text file in your working directory WILL bear CRLF line endings and git status should still consider the workdir as clean.
The Wall of Pink shouldn't appear from now on when creating new commits.
Note: The wall of pink may still appear while displaying the changes between two commits in your history that were created before the commit containing the .gitattributes file.
Open the file in the Notepad++.
Go to Edit/EOL Conversion.
Click to the UNIX/OSX Format.
Save the file.

Resources