question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

LFS Merge Conflict Merges Pointers

See original GitHub issue

Description

When merging into a branch while using Git LFS, it attempts to merge the LFS pointers together. We then have to manually change the files by removing the pointer we don’t want. I would have expected to be prompted with “Take Incoming File” or “Keep Current File” for our LFS files.

Version

  • GitHub Desktop: 1.6.5
  • Operating system: Microsoft Windows [Version 10.0.17763.379]

Steps to Reproduce

  1. Create a merge conflict between two LFS files in two different branches.
  2. Attempt to merge one branch into the other branch with the merge conflict, and you will see that the conflict was “automatically resolved” when all it did was merge the pointers together.

Expected Behavior

Be prompted with “Take Incoming File” or “Keep Current File” for LFS files.

Actual Behavior

The LFS pointers are merged together into one file and breaks the LFS pointer.

Additional Information

Logs

2019-03-26.desktop.production.log

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:4
  • Comments:57 (13 by maintainers)

github_iconTop GitHub Comments

6reactions
TCROCcommented, Mar 26, 2019

@shiftkey Hey thanks for getting back with me 😃 I created a test repo here. All you have to do is clone the repo in GitHub Desktop. Merge the branch ‘master’ into ‘DevBranch2’ and commit the merge. Then open ‘LFSTrackedFile.asset’ in a text editor (I tested it in Notepad, Notepad++, and VS Code). The results should look like this:

version https://git-lfs.github.com/spec/v1
<<<<<<< HEAD
oid sha256:6b11f7689252ef9a2ae45a0949db32457b0404ffd27fbe399685da21efe06c46
size 51
=======
oid sha256:88169783c65ba3ceeff49a02a88e37c08b10d82b05368fe16792ede6d68db380
size 62
>>>>>>> master

I realize all we have to do is pick the merge ourselves in a merge tool / text editor and is plenty easy for us developers to do, but this is not intuitive for our artists (we are a game dev team). We simply want to be able to do an “Accept Incoming Change” or “Accept Current Change” from GitHub Desktop like we currently have to do in VS Code.

Here are some example pics of what we see:

Before comitting merge:

No Conflicts Remaining Message

What we expect to see before committing merge. Pic was taken with a normal merge conflict (not LFS).

Expected Output For LFS File

The file after merging:

Automatically Merged File

The during merge screen would be nice if there were “Accept Incoming Change” or “Keep My Change” buttons. This would be much more intuitive for our artists. However, we don’t even get the option as seen in the expected image. Currently our artists have to open a command prompt and enter git mergetool and take the merges by hand.

Again thanks for looking into this for us 😃

5reactions
matteblaircommented, Feb 9, 2021

Thanks for the thorough and helpful discussion on this issue! I’ve encountered this problem too (also with art files in a Unity project) and so I’ve tried the work-around using the binary attribute. I found some details that may be helpful to others.

The work-around described above is to append the binary attribute to the usual LFS attribute list, producing this attribute list: filter=lfs diff=lfs merge=lfs -text binary. I can confirm that GitHub Desktop does use manual conflict resolution for files using this attribute list, which resolves the issue. But how does this actually affect the attributes that git is applying to these files? I used git check-attr to find out.

With the usual LFS attribute list (filter=lfs diff=lfs merge=lfs -text) we get these attributes:

LFSTrackedFile.asset: diff: lfs
LFSTrackedFile.asset: merge: lfs
LFSTrackedFile.asset: text: unset
LFSTrackedFile.asset: filter: lfs

And with binary added (filter=lfs diff=lfs merge=lfs -text binary) we get these attributes:

LFSTrackedFile.asset: binary: set
LFSTrackedFile.asset: diff: unset
LFSTrackedFile.asset: merge: unset
LFSTrackedFile.asset: text: unset
LFSTrackedFile.asset: filter: lfs

The binary attribute is set, but now the diff and merge attributes are unset! This is because binary is in fact a macro attribute that, when applied, unsets the diff, merge, and text attributes.

What is the effect of having diff and merge unset instead of set to the value lfs? Unclear! Unlike filter, I believe that git LFS does not currently do anything with these attributes and that they are reserved for some future use.

Ideally, you’d want to keep those attributes as-is to avoid potential issues with LFS. You can do this by putting the binary attribute before the LFS attributes, as in: binary filter=lfs diff=lfs merge=lfs -text. This produces the attributes:

LFSTrackedFile.asset: binary: set
LFSTrackedFile.asset: diff: lfs
LFSTrackedFile.asset: merge: lfs
LFSTrackedFile.asset: text: unset
LFSTrackedFile.asset: filter: lfs

This seems like exactly what we want! Except that GitHub Desktop does not use manual conflict resolution for files with these attributes (which is the whole point of this work-around).

By experimentation, I’ve found that GitHub Desktop will only use manual conflict resolution on files that have the diff attribute unset. Why? My best guess is this: https://github.com/desktop/desktop/blob/8bdb92182138ffc23691f81b4278b1a3002abbe8/app/src/lib/git/diff.ts#L438-L456 This function is calling git diff --numstat and scanning the output for patterns that indicate a “binary” file, according to git. In my testing, I’ve found that the cases where GitHub Desktop uses manual conflict resolution correspond exactly to when git diff --numstat classifies a file as “binary”.

TL;DR A “minimal” work-around for this issue is to change the attributes in your .gitattributes file for LFS files to

filter=lfs merge=lfs -diff -text

But be aware that this (or the binary attribute) may cause issues with future versions of LFS.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Web based conflict resolution for merges breaks git lfs pointer ...
When using GitLab's interface for conflict resolution in merges, git lfs pointer files are saved without a newline at the end of the...
Read more >
How to merge the content of files tracked by Git LFS
I was considering using Git LFS to handle it. By checking the documentation I am not sure if Git LFS supports the actual...
Read more >
Recovering From a File That Should Have Pointers in Git
$ git merge origin/master warning: Cannot merge binary files: [filename] (HEAD vs. origin/master) Auto-merging [filename] CONFLICT (content): ...
Read more >
git-lfs-merge-driver(1) - Debian Manpages
Merge text files stored in Git LFS using the default Git merge machinery, or a custom merge driver if specified. Note that this,...
Read more >
Git Merge | Atlassian Git Tutorial
How it works · Preparing to merge · Confirm the receiving branch · Fetch latest remote commits · Merging · Fast Forward Merge...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found