Git + Windows + Visual Studio Merge Conflicts Caused by Line Ending Issues between branches

99823 picture 99823 · Feb 20, 2017 · Viewed 7.2k times · Source

I'm having a difficult time trying to properly merge to branches. The branches seem to have line ending issues because when I open up the conflict window in Visual Studio its showing 0 conflicts and 0 differences between numerous files.

I've added a gitattributes file on both branches that looks and performed a repository refresh on both repositories.

When I refreshed both repositories there were no changes to commit, even though the instructions stated there would be changes to commit (essentially the changes being from the EOL conversions).

Here is my gitattributes

# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs     diff=csharp

# Standard to msysgit
*.doc    diff=astextplain
*.DOC    diff=astextplain
*.docx   diff=astextplain
*.DOCX   diff=astextplain
*.dot    diff=astextplain
*.DOT    diff=astextplain
*.pdf    diff=astextplain
*.PDF    diff=astextplain
*.rtf    diff=astextplain
*.RTF    diff=astextplain

I've also checked and my global core.autocrlf is equal to true (since all our devs are using Visual Studio on Windows)

The problem is, as I continue to do the above in hopes of fixing and normalizing these line branches across the two branches I end up with even MORE conflicts than previously - all due to line ends:

enter image description here

.git/config file (not including branch refs)

[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
    hideDotFiles = dotGitOnly
    autocrlf = true
[merge]
    renormalize = true

I'm at my wits end, going through countless SO questions/answers - googling, to no avail - my conflict count continues to rise.

Also note: I'm using GIT on TFS - not sure if this changes things.

UPDATE 1: I've copied the said "conflicting" two files out from Visual Studio, each into their own Notepad++ windows with "show symbols -> show end of line" turned on - then I compared both "conflicting" files and as you can see there is NO difference in the line endings (both files contain the exact same CR/LF's as shown in the image below) - so i'm guessing that VS is doing its EOL conversion or something? OR when I copy it out into Notepad++ its doing some sort of EOL conversion? Not sure if this helps at all.

enter image description here

I am running Visual Studio 2015 Update 3

Update 2: I've added this handy End of Line Visual Studio Extension that shows the files EOL characters so I can see all the EOL characters right in the merge / diff screen and it appears they match exactly between the files.

Update 3: OK - so I think i may be on to something here... I did a merge, then opened a conflicting file and this is what i found... the branch i'm merging FROM is using CRLF's, the branching i'm merging INTO is using LF's - so it does appear to be and EOL issue. I'm not sure how I can bulk fix this though? I though my initial repository refreshes I listed above would do this, apparently not.

Here is master (merging into master NOTE: this file is CRLF BEFORE merging, upon merging the CRLFs must be being converted to LF): enter image description here

Here is what i'm merging from: enter image description here

Answer

Dawid Dworak picture Dawid Dworak · Feb 21, 2017

To be more consistent and be able to specify the line ending for different files by the extension, you can use .gitattributes file. The file is committed to the repository and will override the developers setting. The .gitattributes file should be created in the root of the repository and committed into the repo like any other file.

# Set behaviour for all files, in case developers don't have core.autocrlf set.
* text=auto

# Explicitly declare text files we want to always be normalized and converted to native line endings on checkout.
*.txt 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.
*.zip binary