简体   繁体   中英

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

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:

在此输入图像描述

.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.

在此输入图像描述

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): 在此输入图像描述

Here is what i'm merging from: 在此输入图像描述

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

If you are using core.autocrlf = true, then in repo (TFS) all files are stored with LF, while on checkout GIT converts them to CRLF. The problem I've noticed with auto is according to documentation

"When the file has been committed with CRLF, no conversion is done."

So basically if you have some files in repository commited with CRLF, because conversion wasn't performed, in other branch you have normalized line endings (LF), then you receive conflicts uppon merge. It's hard to see it because when you checkout, LF are replaced with CRLF and there seems to be no changes.

My approach is using CRLF as eol instead of auto, hoping that it will always replace CRLF -> LF on commit and LF -> CRLF on checkout.

*.cs                  text eol=crlf
*.xaml                text eol=crlf
*.csproj              text eol=crlf
*.sln                 text eol=crlf

So to solve your issue you have to change on server line endings from CRLF to LF. For me this command worked .gitattributes was modified and commited (even if I cannot explain it, but I got all the files with CRLF changed to LF on repository)

git rm --cached -rf .
git diff --cached --name-only -z | xargs -n 50 -0 git add -f

And another thing, after changing .gitattributes you have to checkout your files again, I'm using this commands for it:

git rm -rf --cached .
git reset --hard HEAD

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM