What do the Angular CLI's `ng update` flags `--create-commits` and `--allow-dirty` change, and why does a clean working tree matter?
answer
- one commit for the install
- one commit per migration
- commit message carries the description
- dirty tree refused by default
- reviewable, revertible steps
basics
~20 s--create-commits (-C) commits the version changes, then each migration separately with its name and description. --allow-dirty lets the update run with uncommitted changes, which it otherwise refuses, at the cost of mixing your edits into the update's diff.
solid answer
~40 sBy default `ng update` refuses to run when the repository has modified or untracked files, with `Repository is not clean. Please commit or stash any changes before updating.` That keeps the update's changes separate so they can be reviewed or thrown away with git. `--allow-dirty` overrides the check and only warns that the changes will be mixed with pre-existing ones. `--create-commits`, alias `-C`, makes the CLI commit as it goes. First comes a commit for the package updates (`Angular CLI update for packages - ...`). Then each migration that changed files gets its own commit, titled `<package> migration - <migration name>` with the migration's description as the body. The result is a reviewable history where each automated change can be inspected, reverted or bisected on its own.
code
bash · 6 linesgit status --short # empty: OK to update
ng update @angular/core@22 @angular/cli@22 -C
git log --oneline -4
# <sha> @angular/cli migration - <migration name>
# <sha> @angular/core migration - <migration name>
# <sha> Angular CLI update for packages - @angular/core@22, @angular/cli@22go deeper
Know to commit or stash before ng update, and that the CLI refuses otherwise unless told to allow it.
Explain what --create-commits commits and when, and what --allow-dirty does and does not do.
Use per-migration commits for review, bisect and selective revert, and keep --allow-dirty to throwaway or CI-generated situations.
Make automated update branches with per-migration commits the team's standard, so framework upgrades are routine, reviewable changes.
## Why the CLI cares about git at all An `ng update` across a major can touch dozens of files: `package.json`, the lockfile, `angular.json`, tsconfig files, and source code rewritten by migrations. If that lands on top of half-finished work, nobody can tell which change came from where, and "undo the update" is no longer a single git command. So the CLI makes git state part of the contract. ## `--allow-dirty`: the clean-tree check When you name packages, `ng update` checks the working tree inside the workspace: - **Clean**: the update proceeds. - **Modified or untracked files, no flag**: it stops with `Repository is not clean. Please commit or stash any changes before updating.` - **`--allow-dirty`**: it proceeds with a warning that update changes will be mixed with pre-existing changes. The check looks at files inside the workspace root, so unrelated changes elsewhere in a larger repository do not block it. `ng update` without packages only lists available updates and does not check. Use `--allow-dirty` sparingly. Legitimate cases are a CI job that has generated files it will discard anyway, or a scratch experiment you intend to throw away. ## `--create-commits`: history you can review `--create-commits` (alias `-C`) commits at two points: 1. **After a successful install**: one commit containing `package.json` and lockfile changes, titled `Angular CLI update for packages - <packages>`. 2. **After each migration that modified files**: one commit per migration, titled `<package> migration - <migration name>`, with the migration's description as the commit body. The benefits are concrete: - **Review.** Reviewers read one migration at a time instead of a single large diff. - **Bisect.** If the app breaks, `git bisect` points at the exact migration. - **Selective revert.** A migration whose change you want to redo by hand can be reverted alone. - **Documentation.** The descriptions in the commit bodies explain *why* each file changed. If a commit fails, the CLI aborts the update rather than continuing without history. ## Putting them together | Situation | Flags | |---|---| | Normal local update | clean tree, optionally `-C` | | Update for a pull request others will review | clean tree, `-C` | | CI job applying updates automatically | clean checkout, `-C` so the branch history shows each step | | Quick experiment on a throwaway branch | `--allow-dirty` acceptable | ## A reviewable update branch, step by step 1. Start from an up-to-date main branch with a clean tree, and create a branch for the update. 2. Run `ng update @angular/core@^22 @angular/cli@^22 -C`. The branch now holds an install commit plus one commit per migration that changed files. 3. Run the build and tests. Add your own fix-up commits on top, clearly separated from the automated ones. 4. Open the pull request. Reviewers step through the commits: version changes first, then each migration with its description, then the human fixes. 5. Squash or keep the history according to team convention. Keeping it pays off when a regression appears weeks later and `git bisect` lands on a single migration commit. ## Related safety nets - If the package install fails, the CLI restores the original `package.json`, and the clean tree lets `git checkout .` handle everything else. - Migrations run on the schematics virtual tree, so a migration that throws does not leave half-written files. A failure stops the run and reports which migration failed. ## Common misunderstandings - `--allow-dirty` does not stash or protect your changes; it only disables the check. - `--create-commits` does not push, open pull requests or tag anything. - Neither flag affects which versions are chosen or which migrations run.
- A migration's change is wrong for your codebase. How does `--create-commits` help?That migration's changes sit in their own commit, titled with the migration's name. You can `git revert` just that commit and redo the change by hand, keeping the version bump and every other migration. Without per-migration commits you would have to untangle it from one large diff.
- Why doesn't `ng update` stash your changes automatically instead of refusing?Stashing and re-applying can conflict with files the migrations rewrite, leaving a mess that is harder to recover than the original refusal. Refusing puts the decision with you: commit, stash or discard first, or accept mixing with `--allow-dirty`.
saying these in an interview costs you the question
- Believes --allow-dirty stashes local changes and restores them later
- Thinks --create-commits pushes the branch or opens a pull request
- Expects one single commit containing all migrations with -C
- Uses --allow-dirty routinely and then cannot tell edits from migrations
- Assumes the clean-tree check also runs for ng update with no packages