Open-Source Wikis

/

Angular

/

How to contribute

/

Development workflow

angular/angular

Development workflow

The branch / commit / review / merge cycle, end to end.

1. Setup

If you haven't yet, follow overview/getting-started to clone, install with pnpm, and verify a Bazel test runs. Add upstream as a remote pointing at https://github.com/angular/angular.git even when you've forked; the doc samples assume that.

2. Branch from main

git checkout main
git pull --ff upstream main
git checkout -b fix-router-thing

Even patches that will be back-ported to a release branch start from main. Cherry-picking is automated by ng-dev release based on PR labels.

3. Make focused changes

  • One logical change per PR. Refactors that aren't strictly required by the feature go in a separate PR.
  • Update tests in the same commit as the code under test.
  • If the change touches a public API, run pnpm public-api:update and include the resulting .d.ts diff under goldens/public-api/.
  • If the change adds new directives, components, or symbols, the pnpm symbol-extractor:update snapshot under goldens/size-tracking/ may also need refreshing.

4. Format and lint

pnpm ng-dev format changed   # Format files changed since `main`
pnpm lint                     # tslint + format-check

The pre-commit hook installed by husky (see .husky/) runs ng-dev format and commit message validation automatically.

5. Run the tests that matter

Targeted tests during iteration:

pnpm bazel test //packages/core/test:test
pnpm bazel test //packages/router/test/...

Before opening the PR, run the broader suite for the area you touched:

pnpm test:ci   # everything except integration / docs site / devtools

6. Commit with the conventional format

git commit -m "fix(router): cancel pending nav on subsequent navigation"

The body should explain the why, not the what — diffs already show the what. If your change has any user-visible impact, write a body of 20+ characters explaining motivation. The body becomes part of the changelog.

For breaking changes, the footer must include BREAKING CHANGE: followed by migration guidance:

BREAKING CHANGE: `ActivatedRoute.params` is now an Observable<Params>
that emits a new value when navigation completes.

Before:
  this.route.params.subscribe(params => ...);

After: same, but the Observable emits more eagerly.

7. Push and open the PR

git push origin fix-router-thing
gh pr create --base main --title "fix(router): cancel pending nav on subsequent navigation" --body ...

The repository expects the gh CLI for managing pull requests (per AGENTS.md). The PR template prompts for type, issue link, and breaking-change confirmation.

8. Address review feedback with fixup commits

Reviewers leave inline comments. Address them with fixup commits, which preserve review history:

git commit --all --fixup HEAD
git push

When the reviewer approves, the merge tooling will autosquash before merging. You can preview locally:

git rebase -i --autosquash main

The detailed walkthrough lives in contributing-docs/using-fixup-commits.md.

9. Merge

The Angular caretaker (a rotating role; see contributing-docs/caretaking.md) attaches action: merge and the target: minor/patch/major label. The angular-robot automation then:

  1. Verifies CI is green.
  2. Squashes the fixup commits.
  3. Cherry-picks to the labeled release branch when applicable.
  4. Pushes the merged commit to main.

The PR is closed by the bot, not by the contributor's git push.

10. Post-merge

After your PR lands:

  • A snapshot build publishes to angular/<package>-builds automatically. Apps can depend on the snapshot to verify the fix in their codebase.
  • The next biweekly release picks up your change. The release: cut the v… commits visible in git log are produced by pnpm ng-dev release publish.

Working on multiple PRs

The release tooling reads PR labels to determine which release branch to cherry-pick to. Don't manually cherry-pick or open duplicate PRs against release branches — the bot handles it.

For branches dependent on each other ("stacked PRs"), open them sequentially and rebase as the parent is merged. There is no built-in stacked-PR tooling.

Common pitfalls

  • Forgetting the public API golden update. CI fails with a diff and a hint to run pnpm public-api:update. Run it locally and commit the result.
  • Symlink errors when running CLI builds. Pass --preserve-symlinks --preserve-symlinks-main to node when running the CLI against locally built @angular/* packages (see contributing-docs/building-and-testing-angular.md).
  • Tests pass locally but fail on CI. Almost always Bazel cache state. pnpm bazel clean --expunge resets fully.
  • Pre-commit hook complains about commit message format. The header must match <type>(<scope>): <summary> exactly. If husky won't let you commit, run pnpm ng-dev commit-message validate-file <commit-msg-file> to see the precise failure.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – Angular wiki | Factory