How can I tell if a file will be uploaded to git lfs correctly?

Senseful picture Senseful · Jan 31, 2019 · Viewed 14.2k times · Source

I'm trying to add everything under MyProject/Frameworks/ to git-lfs (large file storage). I'm not sure what the proper format for matching all files and folders recursively under the Frameworks folder is. This answer says the proper format is git lfs track "MyProject/Frameworks/**", but Atlassian's help document says I should use git lfs track "MyProject/Frameworks/". I tried both and they didn't use git lfs for storage. It tried uploading files directly.

Sure, I'd love to know the proper format, but more importantly, before I attempt to push my changes to github, I'd like to verify that the match and files do indeed work correctly. This'll allow me to iterate and try new things.

I see two related commands that might help: git lfs status and git lfs ls-files. It's not clear which one I should be using and what output I should be looking for. For example, when I ran git lfs status, it showed me a ton of files under Git LFS objects to be committed, making me think they would be added to Git LFS. However, after attempting to push to GitHub.com, I realized that it was clearly not the case. If it helps, the output for these files always had something like (Git: edee1ad) after each file name.

When I attempt to use git lfs ls-files I'm not sure if I need to run it after git adding the files, after committing them, or after pushing them. Most of the time it's just showing me blank output.

Essentially the question is: If I configured git lfs correctly, what tool (e.g. git lfs status) should I use, and what output should I look for before I attempt to commit/push?

Note: Please don't answer the question with only how to match all recursive files as that will help me once (this specific case), rather than allowing me to iterate and try new things (any case).

Answer

Senseful picture Senseful · Jan 31, 2019

TL;DR

If everything is set up correctly, you can verify that git LFS is going to work properly by:

  1. git add the file(s) in question.
  2. Do one of the following:
    • Run git lfs status and ensure the file(s) in question appear under Git LFS objects to be committed, and that they have the LFS value in parenthesis; or
    • Run git lfs ls-files and ensure the file(s) in question appear in this output.

⚠️ Important: After running git lfs track, you must run git add to refresh the state of files before calling git lfs status or git lfs ls-files. Otherwise you'll see irrelevant output from those commands.

Also, for the record, looks like git lfs track "MyProject/Frameworks/**" is the correct one for recursive matching.


Set up and testing methodology:

  1. git lfs track "*.lfs". This generates .gitattributes. Leave it unstaged.
  2. Create a file in the root directory, Test.lfs. Leave it unstaged.
  3. Test:

    • git lfs status: no filenames output

      $ git lfs status
      On branch master
      Git LFS objects to be pushed to origin/master:
      
      
      Git LFS objects to be committed:
      
      
      Git LFS objects not staged for commit:
      
      
      $
      
    • git lfs ls-files: no output

      $ git lfs ls-files
      $
      
  4. Add git add Test.lfs.

  5. Test:

    • git lfs status: Test.lfs will now be listed with an LFS suffix.

      $ git lfs status
      On branch master
      Git LFS objects to be pushed to origin/master:
      
      
      Git LFS objects to be committed:
      
              Test.lfs (LFS: 2ab9f1e)
      
      Git LFS objects not staged for commit:
      
      
      $
      
    • git lfs ls-files: Test.lfs will now be listed.

      $ git lfs ls-files
      2ab9f1e447 * Test.lfs
      $
      
  6. Commit changes.

  7. Test:

    • git lfs status: Test.lfs will move to the "to be pushed" section. It will have a suffix such with a bunch of numbers/letters.

      $ git lfs status
      On branch master
      Git LFS objects to be pushed to origin/master:
      
              Test.lfs (2ab9f1e44720efb7a26553e06b667a270320efb3e906553b3f9e0702538a2b3f)
      
      Git LFS objects to be committed:
      
      
      Git LFS objects not staged for commit:
      
      
      $
      
    • git lfs ls-files: Test.lfs will continue to be listed.

      $ git lfs ls-files
      2ab9f1e447 * Test.lfs
      $
      
  8. Push changes. Including adding/committing/pushing .gitattributes.
  9. Test:

    • git lfs status: no filenames output anymore

      $ git lfs status
      On branch master
      Git LFS objects to be pushed to origin/master:
      
      
      Git LFS objects to be committed:
      
      
      Git LFS objects not staged for commit:
      
      
      $
      
    • git lfs ls-files: Continues to output the tracked file

      $ git lfs ls-files
      2ab9f1e447 * Test.lfs
      $
      

Conclusions:

  • The Git LFS objects not staged for commit section seems misleading as it never displayed any files, even those that should have been tracked by LFS.
  • If you attempt to do the previous experiment with a non git-lfs tracked file, you'll also notice that it appears under the Git LFS objects to be committed incorrectly. It is not a Git LFS object. The way you can tell that it's not actually a Git LFS object though is to look at how it ends. If it ends with (Git: 111111111) it won't be committed to LFS.
  • To avoid the above confusions, you may want to favor git lfs ls-files over git lfs status to determine if something is going to be part of git-lfs or not.
  • Another gotcha: Some applications such as Xcode will git add files in a weird way causing what should have been clear matches to not be considered for Git LFS. The solution is to unstage the files and then re-stage them.