Why Does npm version Create an Automatic Commit and Tag?
If you have ever run the npm version
command and suddenly noticed Git creating a commit and a tag without your explicit instruction, you are not alone. Many developers are surprised the first time they encounter this behavior. Let’s dive into what’s happening, why npm does this by default, and what options you have to control it.
What npm version
Actually Does
When you run a command such as:
npm version patch
npm performs a series of actions behind the scenes:
- Bumps the version number in your
package.json
.- A
patch
bump increases1.2.3
→1.2.4
. - A
minor
bump increases1.2.3
→1.3.0
. - A
major
bump increases1.2.3
→2.0.0
.
- A
- Updates related files such as
package-lock.json
ornpm-shrinkwrap.json
. - Creates a Git commit with the message
vX.Y.Z
(matching your new version). - Creates a Git tag pointing to that commit.
This behavior is intentional: npm assumes you want your versioning to be tracked in Git history, which is extremely common in open source projects and for packages published to the npm registry.
Why Automatic Commits and Tags Can Be Useful
- Version traceability: Every release is tied to a specific commit. If a bug appears in version
1.2.4
, you can easily see the exact code that was published. - Publishing consistency: The tag ensures that the source code matches the version on npm.
- Automation hooks: You can attach scripts to lifecycle hooks like
preversion
,version
, andpostversion
inpackage.json
for tasks such as building, testing, or publishing.
For teams practicing semantic versioning, this workflow aligns well with continuous release pipelines.
When Automatic Commits and Tags Are a Problem
However, not every project needs this behavior. Examples:
- Private repos or internal tooling where version bumps are just for internal bookkeeping.
- Monorepos where you handle versioning through another tool (e.g., Lerna, Changesets, or Nx).
- Custom release processes where you want commits and tags created only after certain CI/CD checks.
In such cases, the default behavior feels intrusive.
How to Disable the Automatic Commit
To prevent Git commits and tags, you can use:
npm version patch --no-git-tag-version
This updates only your package.json
(and lock file) without touching Git.
If you want this to be the default behavior for your project, set it in your .npmrc
:
git-tag-version=false
From then on, npm version
will only bump the numbers unless you explicitly override it.
Other Considerations
preversion
runs before the version is bumped.version
runs after files are updated but before commit/tag.postversion
runs after commit and tagging.- CI/CD and Versioning Strategy
If your team uses a release pipeline (e.g., GitHub Actions, GitLab CI, Jenkins), you might want to centralize version bumps in CI, not on local developer machines. In that case, using--no-git-tag-version
locally and letting CI handle tagging is a safer approach. - Monorepo Tools Conflict
If you’re using tools like Lerna or Changesets, those tools manage version bumps, changelogs, and tags in bulk. Mixingnpm version
with them can cause inconsistencies. - Version Control Discipline
Remember that automatic commits may clutter your Git history if you bump versions often. Some teams prefer manual control to keep history clean and meaningful.
Pre- and Post- Scripts
You can define lifecycle scripts in package.json
:
{
"scripts": {
"preversion": "npm test",
"version": "npm run build",
"postversion": "git push && git push --tags"
}
}
This is powerful for enforcing checks or automating deployment steps.
Custom commit messages
You can change the default commit message with:
npm version patch -m "Release version %s"
%s
will be replaced with the new version number.
Best Practices
- For open source libraries: Keep the default behavior. Commits and tags help external users trace issues.
- For internal apps/tools: Disable Git tagging unless you publish artifacts externally.
- For CI/CD-driven releases: Use
--no-git-tag-version
locally and let CI pipelines handle version commits and tags. - Always push tags if you rely on them for releases. Tags left only in your local repo are invisible to collaborators.
Finally
The automatic commit and tag in npm version
is not a bug — it’s a deliberate feature designed for a particular workflow: reproducible, traceable releases. That said, npm gives you the flexibility to opt out if it does not suit your project.
Whether you embrace or disable this feature depends on your project’s release strategy, team workflow, and tooling ecosystem. Understanding these behaviors up front ensures you avoid unexpected commits in your history while still leveraging npm’s powerful versioning tools effectively.
Comments ()