Safeguard
Developer Tools•

How do you pin a forked dependency to an exact commit in pip and npm?

Point pip and npm at your fork with a full commit hash, not a branch. A branch moves under you. A commit does not. Syntax, tradeoffs and what to record.

Safeguard Security Team
3 min read

Reference the fork by Git URL and end it with a full commit hash. In pip use the git plus https form with an at sign and the hash. In npm use a Git URL ending in a hash and the commit-ish. A branch or default-branch reference moves, so your build can change without any commit in your repo.

Why a commit, not a branch

If your manifest says "my fork, branch main", every install may get different code. Someone with push access to the fork, or an attacker who took over that account, changes what you ship without touching your repository. A full commit hash fixes the code to one exact state. Reviewing the dependency then means reviewing one commit.

pip

The pip documentation shows Git references with a branch, a tag or a commit hash, and states that a full hash is preferable to a partial one because it lets pip work more efficiently with fewer network calls. In a requirements file:

examplelib @ git+https://github.com/acme/examplelib.git@FULL_COMMIT_HASH

Tags are better than branches but can be moved, so the hash is the stronger pin.

npm

The npm package.json documentation says a Git URL dependency can end with a commit-ish, and that when one is provided it is used to clone exactly that commit. If no commit-ish or semver is given, the default branch is used. In package.json:

"dependencies": {
  "examplelib": "git+https://github.com/acme/examplelib.git#FULL_COMMIT_HASH"
}

npm also supports a semver form after the hash symbol, where it looks for tags matching a range. That is convenient but looser than a hash.

Tradeoffs against a published package

ApproachProCon
Git URL plus full hashNo registry needed, exact codeNo registry advisories, slower installs, needs repo access in CI
Fork published under a new nameNormal installs, version numbersAdvisories for the original may not match
Fork published under a scope you controlFamiliar tooling, signing optionsYou now run a package, with all the duties

Git URL pins suit a short term measure while you wait for upstream. See carrying a patch while waiting for an upstream merge.

Checklist

  1. Use the full hash and write the upstream base version in a comment or a nearby note.
  2. Make the fork repository private or access controlled if it contains unreleased fixes, and restrict who can push.
  3. Protect the fork's branches so the pinned commit cannot be rewritten out of existence.
  4. Add the dependency to your fork register with an owner and a removal condition.
  5. Rescan after each change, since registry based tools may not see Git sourced packages the same way.

The last point is the quiet one. Scanners vary in how they treat Git URL dependencies, so test yours with a known fork before relying on it. See will scanners flag a renamed fork.

Where Safeguard fits

Safeguard's dependency scanning and policies can be used to review what your builds resolve, including changes to dependency sources in a pull request. Try a free scan at gold.safeguard.sh/scan.

Quick check

Why not pin to a tag?

Tags can be moved or deleted and recreated. A full commit hash cannot point anywhere else.

What does npm do with no commit-ish on a Git URL?

It uses the default branch, which can change between installs.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.