Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Execute FetchCommand with removeDeletedRefs enabled fails with LOCK_FAILURE #153

Open
Shawyeok opened this issue Mar 21, 2025 · 0 comments

Comments

@Shawyeok
Copy link

Shawyeok commented Mar 21, 2025

Version

7.2.0

Operating System

MacOS, Linux/Unix

Bug description

When executing JGit's FetchCommand with setRemoveDeletedRefs(true), the operation fails with LOCK_FAILURE when attempting to delete remote-tracking branches that have been deleted from the remote repository. This occurs specifically when new branches are created with names that are prefixes of the deleted branches.

Use Case Context

Many CI/CD and build systems maintain a local cache of Git repositories to:

  • Reduce network bandwidth usage
  • Speed up build times
  • Minimize load on Git servers

These cache repositories typically:

  • Only perform fetch operations to stay up-to-date
  • Use checkout operations to switch to specific revisions
  • Never perform write operations other than updating remote refs
  • Need to clean up deleted remote refs to prevent accumulation of stale references

Steps to Reproduce

  1. Initial Setup:

    # Create and initialize original repository
    mkdir original-repo && cd original-repo
    git init
    
    # Create initial commit
    echo "test" > test.txt
    git add test.txt
    git commit -m "Initial commit"
    
    # Create a branch with a longer name
    git checkout -b qa/20250321
    git push origin qa/20250321
  2. Clone Setup:

    # Clone the repository
    git clone original-repo /tmp/repoCloned
  3. Branch Manipulation:

    # In original repository
    git push origin --delete qa/20250321  # Delete remote branch
    git branch -d qa/20250321            # Delete local branch
    
    # Create new branch that is a prefix of deleted branch
    git checkout -b qa
    git push origin qa
  4. Run the following Java code against the cloned repository:

    import java.io.File;
    import java.io.IOException;
    import org.eclipse.jgit.api.Git;
    import org.eclipse.jgit.api.errors.GitAPIException;
    import org.eclipse.jgit.lib.RefUpdate;
    import org.eclipse.jgit.transport.FetchResult;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    class Scratch {
        private static final Logger log = LoggerFactory.getLogger(Scratch.class);
    
        public static void main(String[] args) throws IOException, GitAPIException {
            Git git = Git.open(new File(args[0]));
            FetchResult fetchResult = git.fetch()
                    .setRemoveDeletedRefs(true)
                    .call();
            fetchResult.getTrackingRefUpdates().forEach(refUpdate -> {
                if (refUpdate.getResult() == RefUpdate.Result.LOCK_FAILURE) {
                    log.info("LOCK_FAILURE: [{}] local={}, remote={}", 
                            refUpdate.asReceiveCommand().getType(),
                            refUpdate.getLocalName(), 
                            refUpdate.getRemoteName());
                }
            });
        }
    }

Actual behavior

The operation fails with LOCK_FAILURE when attempting to update the references. Example output:

Expected behavior

The fetch operation should successfully remove the deleted remote-tracking branch (qa/20250321) and create the new remote-tracking branch (qa), keep consistent with git fetch --prune.

Relevant log output

Other information

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant