LFS objects are not cleaned, when push is rejected by pre-receive hook

Hello,

We used to have a standard git repo, which had plenty of binary files. We used a pre-receive hook to parse the headers of the files and see if they follow our standard. Now we want to move to LFS for these files and accordingly reworked the pre-receive hook to cancel the push if we spot an issue with the files being pushed. This works in the following way:

  1. An user pushes a commit with binary files
  2. LFS pushes first the binary objects
  3. GIT pushes the rest of the source code
  4. pre-receive hook starts and checks the binary files

If on step 4 we want to cancel the push, this is okay. However the binary LFS objects stay in the LFS store and use space. I ran manually:
“remove_unreferenced_lfs_objects_worker” background job, but the files are still there.

Is this an expected behaviour? What would be appropriate cleanup steps?

Regards

In order to reproduce it, you need to create a git hook under “/var/opt/gitlab/git-data/repositories/[@hashed/]yourrepo.git/custom_hooks/pre-receive” (must be executable):

#!/bin/bash

# Pre-receive hook that will block any new commits that contain dds files with invalid format

errorLevel=0
zero_commit="0000000000000000000000000000000000000000"

# Do not traverse over commits that are already in the repository
# (e.g. in a different branch)
# This prevents funny errors if pre-receive hooks got enabled after some
# commits got already in and then somebody tries to create a new branch
# If this is unwanted behavior, just set the variable to empty
excludeExisting="--not --all"

while read oldrev newrev refname; do
  echo $refname $oldrev $newrev

  # branch or tag get deleted
  if [ "$newrev" = "$zero_commit" ]; then
    continue
  fi

  # Check for new branch or tag
  if [ "$oldrev" = "$zero_commit" ]; then
    span=`git rev-list $newrev $excludeExisting`
  else
    span=`git rev-list $oldrev..$newrev $excludeExisting`
  fi

  for COMMIT in $span;
  do
      while IFS= read -r FILE; do
        case "$FILE" in
          *.bin )
          echo "ERROR: You are not allowed to push \"bin\" files -> \"$FILE\""
          echo "File is located under your lfs object store folder in subfolder:"
          echo "$(git show $newrev:"$FILE" | grep 'oid sha' | awk -F':' '{print $2}' | sed 's/\([a-f0-9][a-f0-9]\)\([a-f0-9][a-f0-9]\)\(.*\)/\1\/\2\/\3/g')"
          errorLevel=1
          ;;
        esac
      done <<< "$(git log -1 --name-only --pretty=format:'' $COMMIT)"
  done
done
exit $errorLevel

enable LFS in a newly cloned test repo:

git lfs install
git lfs track '*.bin'
git add .gitattributes 
dd if=/dev/urandom bs=1M count=1 | gzip -c > ./file.bin
git add file.bin
git commit -m "Add files"
git push origin master