Troubleshooting "git error cannot lock ref"

Greg Foster
Greg Foster
Graphite software engineer


Note

This guide explains this concept in vanilla Git. For Graphite documentation, see our CLI docs.


This guide explains what the error "git error cannot lock ref" means, when it typically occurs, and detailed steps to resolve it effectively.

The "git error cannot lock ref" message typically occurs when Git is unable to update or create a reference (ref) due to a lock. In Git, refs are pointers to commits and are how branches and tags point to specific points in the repository's history. Branches and tags are both different types of Git refs.

Locking a ref is a mechanism that prevents multiple Git processes from writing to the same ref at the same time, thus avoiding corruption or conflicts.

This error might appear in various forms depending on what you are trying to do, such as:

  • git fetch cannot lock ref
  • git error cannot lock ref 'refs/remotes/origin
  • git push error cannot lock ref

There are a few scenarios where this error can occur:

Scenario: Suppose you have two automated scripts that are scheduled to run at the same time. One script is set to push changes to a remote repository while another is set to fetch and merge updates from the same remote repository. Running these two operations concurrently can lead to a situation where one script tries to update refs while the other is already locking them. This could result in one of the operations failing with a "cannot lock ref" error.

Example:

  • Script 1 executes: git push origin main
  • Script 2 executes simultaneously: git fetch origin main && git merge FETCH_HEAD

If these commands overlap, one might fail because the ref refs/heads/main is locked by the other operation.

Join 20,000+ developers at top companies
Stop wrestling with Git commands
The Graphite CLI takes all the pain out of Git, allowing you to ship faster and stop googling Git commands.
main
diff1
diff2

A lock file in Git is a mechanism used to prevent simultaneous access to critical resources, ensuring that only one Git operation can modify a resource, such as a branch or a configuration file, at a time. When a Git operation that alters the repository's data begins, it creates a lock file (.lock) to signal that the resource is in use, preventing other operations from making conflicting changes during this period. Once the operation successfully completes, the lock file is removed, signaling that the resource is free for other operations to access and modify.

Sometimes these lock files can become stale:

Scenario: A Git operation like git commit or git merge was interrupted or crashed, leaving a lock file such as .git/refs/heads/main.lock. When you try to perform another operation that modifies the main branch, Git will complain it cannot lock the ref due to the existing lock file.

Example:

  • You run git commit, but the process is terminated abruptly.
  • You later run git pull and receive an error message because the lock file from the previous commit operation was not removed.

Scenario: Corruption within the .git/refs directory or issues with the packed-refs file can lead to issues with reference updating. If the file is corrupt or contains invalid data, Git might not be able to properly access or update the reference, leading to a locking error.

Example:

  • You have manually edited a file in .git/refs/heads/ or there was a disk write error that corrupted a ref file.
  • When you try to push or pull changes involving this ref, Git fails because it cannot properly parse and thus lock the ref.

Scenario: Namespace collisions occur when two references (branches or tags) end up having the same path in the refs directory. This might happen if you have two branches with the the same name or if two branch names differ only in casing on a case-insensitive filesystem.

Example:

  • You have two branches named feature.
  • Attempting to fetch updates might result in Git being unable to lock the ref because refs/heads/feature and refs/heads/feature cannot be resolved to a distinct reference.
Join 20,000+ developers at top companies
The best engineers use Graphite to simplify Git
Engineers at Vercel, Snowflake & The Browser Company are shipping faster and staying unblocked with Graphite.
main
diff1
diff2

A stale lock file is often the cause of this error. You can resolve this by:

  • Navigate to your Git repository directory.
  • Look for lock files in the .git/refs/ directory and subdirectories, particularly under .git/refs/remotes/ or .git/refs/heads/.
  • Carefully remove any .lock files you find:
    Terminal
    find .git -type f -name '*.lock' -delete

Sometimes, syncing with the remote and cleaning up obsolete references can resolve the issue:

  • Fetch changes from the remote and prune any stale references:
    Terminal
    git fetch --all --prune
  • If you are specifically having trouble with remote references, you might want to prune remote-tracking branches:
    Terminal
    git remote prune origin

While Git is an incredibly useful tool, it has many shortcomings, particularly with rebasing, and managing stacked pull requests.

The Graphite CLI simplifies git, handles rebasing automatically, and allows you to create, submit, and stack pull requests right from the command line.

Under the hood, the CLI runs Git to create branches, commits, and metadata, which means you can still use Git in your scripts, tooling, or whenever you feel like it. Read more about installing the Graphite CLI in our docs.

screenshot of the Graphite CLI

If references are corrupted or if there's a conflict in the references:

  • Check out a new branch to safely modify the refs without affecting your current branch:
    Terminal
    git checkout -b temp-branch
  • Delete the problematic branch locally, and then check it out again from the remote to reset its ref:
    Terminal
    git branch -D branch-name
    git fetch origin
    git checkout branch-name
  • If the issue is with a remote ref, resetting your local copy of the remote branch might help:
    Terminal
    git update-ref -d refs/remotes/origin/branch-name

If the error involves a conflict between branches or tags (e.g.,two branches have the same name), you might need to rename one:

  • Rename the local branch:
    Terminal
    git branch -m old-branch-name new-branch-name
  • Push the renamed branch and reset the local tracking:
    Terminal
    git push origin :old-branch-name new-branch-name
    git branch --unset-upstream
    git branch -u origin/new-branch-name

If, after following these various steps, you are still seeing this error, refer to the official Git documentation on refs.

Graphite
Git stacked on GitHub

Stacked pull requests are easier to read, easier to write, and easier to manage.
Teams that stack ship better software, faster.

Or install our CLI.
Product Screenshot 1
Product Screenshot 2