Description
When using nx release with conventionalCommits: true and automaticFromRef: true in a monorepo, adding a new package causes the release process to scan the entire repository git history instead of only the commits relevant to the new package. This results in severe performance degradation, excessive warnings, and potential CI timeouts.
Root Cause
When a project has no release tags (i.e., it was just added to the monorepo), two code paths fall back to getFirstGitCommit() — the very first commit in the repository:
-
Version resolution (derive-specifier-from-conventional-commits.ts#L43):
const previousVersionRef = latestMatchingGitTag
? latestMatchingGitTag.tag
: fallbackCurrentVersionResolver === 'disk'
? await getFirstGitCommit() // ← scans from the dawn of time
: undefined;
-
Changelog resolution (version-plan-filtering.ts#L168):
if (useAutomaticFromRef) {
return await getFirstGitCommit(); // ← same issue
}
This causes git log <first-ever-commit>..HEAD --name-status to process every commit in the repository, even for a package that was added yesterday.
Reproduction
nx.json:
{
"release": {
"projects": ["packages/*"],
"projectsRelationship": "independent",
"releaseTagPattern": "release/{projectName}/{version}",
"changelog": { "automaticFromRef": true },
"version": {
"conventionalCommits": true,
"fallbackCurrentVersionResolver": "disk",
"generatorOptions": {
"currentVersionResolver": "disk",
"specifierSource": "conventional-commits"
}
}
}
}
Steps:
- Have a monorepo with a long git history (1000+ commits)
- Add a new package (e.g.,
packages/my-new-lib/package.json with "version": "1.0.0")
- Run
nx release --skip-publish
Observed behavior:
- Release step takes 5+ minutes scanning the entire history
- Dozens of warnings for every old/renamed/removed package referenced in ancient commits:
The affected projects might have not been identified properly.
The package(s) <old-package-name> were not found.
- In CI environments, this often exceeds pipeline timeout limits
Expected behavior:
nx release should only scan commits since the project was first introduced
- No warnings for packages that predate the new project
Real-World Impact
In our monorepo (~1200 commits, ~30 packages, 4 newly added packages):
| Metric |
Current |
Expected |
| Commits scanned per new package |
~1200 |
Only since package was added |
| "Package not found" warnings |
~30 per run |
0 |
| Release step time |
5m 30s |
Seconds |
| CI pipeline |
Intermittent timeouts |
Stable |
Proposed Fix
PR #35323 introduces getFirstProjectCommit(projectRoot) which uses:
git rev-list --reverse HEAD --first-parent -- <projectRoot>/package.json
This finds the first commit that touched the project's package.json and returns its parent (so the creation commit is included in from..to ranges). It's used as the fallback instead of getFirstGitCommit() for individual project version resolution and changelog generation.
Workspace-level and fixed release group changelogs continue using getFirstGitCommit() since they have no single project root to scope to.
The function gracefully falls back to getFirstGitCommit() if the project-scoped lookup fails, maintaining full backward compatibility.
Workaround
Until this is resolved, users can create baseline release tags for new packages before running nx release:
# For each release project without a tag, create a baseline tag at HEAD
for project in $(npx nx show projects); do
if [ -z "$(git tag -l "release/${project}/*")" ]; then
version=$(node -p "require('./<project-root>/package.json').version")
git tag "release/${project}/${version}"
fi
done
Environment
- Nx version: 22.5.3 (issue exists in all versions with
automaticFromRef)
- Node: 24.x
- Package manager: pnpm 10.x
- CI: Amazon Linux arm64 — 15 CPUs, 26 GB RAM (c8g.4xlarge)
- Local: macOS Tahoe 26.4.1 — Apple M3 Pro, 18 GB RAM
Description
When using
nx releasewithconventionalCommits: trueandautomaticFromRef: truein a monorepo, adding a new package causes the release process to scan the entire repository git history instead of only the commits relevant to the new package. This results in severe performance degradation, excessive warnings, and potential CI timeouts.Root Cause
When a project has no release tags (i.e., it was just added to the monorepo), two code paths fall back to
getFirstGitCommit()— the very first commit in the repository:Version resolution (
derive-specifier-from-conventional-commits.ts#L43):Changelog resolution (
version-plan-filtering.ts#L168):This causes
git log <first-ever-commit>..HEAD --name-statusto process every commit in the repository, even for a package that was added yesterday.Reproduction
nx.json:{ "release": { "projects": ["packages/*"], "projectsRelationship": "independent", "releaseTagPattern": "release/{projectName}/{version}", "changelog": { "automaticFromRef": true }, "version": { "conventionalCommits": true, "fallbackCurrentVersionResolver": "disk", "generatorOptions": { "currentVersionResolver": "disk", "specifierSource": "conventional-commits" } } } }Steps:
packages/my-new-lib/package.jsonwith"version": "1.0.0")nx release --skip-publishObserved behavior:
Expected behavior:
nx releaseshould only scan commits since the project was first introducedReal-World Impact
In our monorepo (~1200 commits, ~30 packages, 4 newly added packages):
Proposed Fix
PR #35323 introduces
getFirstProjectCommit(projectRoot)which uses:This finds the first commit that touched the project's
package.jsonand returns its parent (so the creation commit is included infrom..toranges). It's used as the fallback instead ofgetFirstGitCommit()for individual project version resolution and changelog generation.Workspace-level and fixed release group changelogs continue using
getFirstGitCommit()since they have no single project root to scope to.The function gracefully falls back to
getFirstGitCommit()if the project-scoped lookup fails, maintaining full backward compatibility.Workaround
Until this is resolved, users can create baseline release tags for new packages before running
nx release:Environment
automaticFromRef)