# Why aren't commits triggering deployments on Vercel?

**Author:** Vercel

---

Commits that don't trigger deployments on Vercel are usually blocked by the Git login connection, commit author verification, or the Ignored Build Step, not by a broken webhook. This guide covers the boundaries that silently reject a commit and the order to check them in.

When a commit lands and no deployment follows, with no error and no comment from the bot, the natural first guess is a broken webhook. The webhook is the visible piece of delivery machinery, but it sits late in the chain. Teams spend afternoons disconnecting integrations and reinstalling GitHub apps when the real cause is a single setting two clicks deep in their account. A silent no-deployment is rarely a delivery failure. More often, a boundary checks the commit, decides it didn't qualify, and declines without surfacing anything. Those upstream boundaries fail more often than the webhook does, and they fail without a visible signal. Ordering the search by likelihood, rather than by what's easiest to see, gets you to the cause faster.

## Key takeaways

- A commit that produces no deployment is usually a configuration boundary rejecting it silently, not a Vercel platform fault or a broken webhook.
  
- The most common cause is an unconfigured Git login connection in Account Settings, and it fails with no error message even when the integration looks connected.
  
- Vercel verifies the commit author has project access before deploying, so a mismatched Git email or a Hobby collaboration limit blocks deploys at the identity layer.
  
- The Ignored Build Step uses inverted exit codes where 0 skips the build, so a script written to Unix conventions silently skips every commit on every branch.
  
- A missing deployment is sometimes correct behavior, because selective skipping through unaffected-project detection and SHA deduplication is a performance feature.
  

## The first suspect is authentication, not the webhook

Check the Git login connection first, because it's the most common cause and the quickest to rule out. When the connection in Account Settings under Authentication isn't configured, commits never create deployments, even for a full member or the owner of the team.

What makes it hard to spot is how healthy everything else looks:

- The integration shows as connected in the dashboard.
  
- The repository appears linked.
  
- Push events arrive at Vercel.
  

Every signal you'd normally check reports that the pipeline is fine, while the one that's broken doesn't surface anywhere obvious.

This is a stateful connection, so it can drift out of sync long after it was set up and working. A few common actions break it:

- A token rotation.
  
- Re-authenticating in GitHub Desktop.
  
- Creating a second Vercel account against the same Git account.
  

The breakage is rarely tied to anything done to the deploy pipeline itself, which is what makes it easy to misread as a webhook problem.

One pattern shows up often enough to name. Automatic deployments run normally one day and stop completely the next, right after a Git provider token-invalidation warning. The developer re-authenticates with the provider, watches the warning clear, and reasonably assumes the loop is closed. Re-authenticating with GitHub is a different action from re-establishing the connection in Vercel account settings, though, and pushes to main keep producing nothing, still without an error. From the outside, the two steps look like one, and that's where the time goes.

To reconnect, go to Account Settings, then Authentication, and reconnect the Git provider directly. One constraint applies: two Vercel accounts can't link to the same Git account. Setting up the link on a second account silently removes it from the first, so anyone who has created a second account should decide which one owns the connection and reconnect from there, rather than fixing one account and breaking the other in the same motion.

## The commit author has to clear the access boundary

Once the connection is healthy, the next boundary is identity, and it has nothing to do with whether the code is correct. Before creating a deployment, the Git integration verifies that the commit author has access to the Vercel project. That check is a security boundary by design. Three identity conditions have to hold for a deployment to trigger, and each one fails quietly in its own way.

### Private repositories require team membership

For a private repository connected to a project that belongs to a team, the person pushing commits has to be a member of the Pro team or the owner of the Hobby team. When the author lacks that access, the Vercel Bot leaves a comment on the commit with a link to request it, which is the system telling you exactly what went wrong.

The more confusing case is when no Bot comment appears at all. That absence is itself a signal, and it usually means pre-deployment validation failed before the Bot ever had a chance to respond. A malformed `vercel.json` is a common trigger, as is a missing Git integration. When the Bot stays silent, the problem sits upstream of the access check, not in it.

### The local Git email must match the provider account

The email configured in the local Git client has to match the email verified with the Git provider account. When the two don't match, Vercel can't confirm the commits are authorized to deploy, and the push goes nowhere. This applies to plus-address emails as well, which is the detail that catches people. `dev+work@example.com` and `dev@example.com` are treated as separate identities, even though they route to the same inbox. Checking the local value takes one command:

`git config --global user.email`

Compare the output against the email registered in GitHub, GitLab, or Bitbucket account settings. If they differ, including by a plus-address, that mismatch is enough to stop deployments.

### Hobby plans enforce collaboration limits

Collaboration has never been permitted on Hobby plans. A previous bug let some teams bypass that limitation, and the fix that closed it now enforces the collaboration limit in GitHub. On a Hobby account, only the account owner can trigger deployments, and contributors who aren't the owner cannot deploy. When a teammate's commits stopped deploying after previously working, this enforcement change is the likely cause. The resolution is to upgrade the project to a Pro team, or to have the account owner perform the deployments.

## Webhook permissions can silently block delivery

Only after the connection and identity checks pass does the webhook become a reasonable suspect, which is later than most people realize. When the Git integration is installed and authenticated correctly, Vercel receives push events through webhooks from GitHub, GitLab, or Bitbucket. Insufficient permissions at any level can prevent delivery without producing a visible error, which is what gives the webhook its outsized reputation as the usual culprit.

Each provider sets a different bar for the access the integration needs:

| Provider  | Required access level |
| --------- | --------------------- |
| GitHub    | Collaborator access   |
| GitLab    | Maintainer access     |
| Bitbucket | Admin access          |

When the Vercel for Git integration is installed with limited repository permissions, the repository being pushed to may not be in scope for the integration. There's also a harder case where the Vercel webhook doesn't exist server-side, even though the dashboard shows everything connected. Community reports document repositories where the expected Vercel webhook never appears in GitHub's settings despite the Vercel side looking complete, and a separate case where one project's webhook subscription dropped server-side while two other projects on the same GitHub App installation kept receiving events normally.

Diagnosing this starts in the repository's webhook settings, then varies by provider:

1. **GitHub:** if no Vercel webhook is listed, disconnect and reconnect the repository in Vercel, or fully uninstall and reinstall the Vercel GitHub App.
   
2. **GitLab:** verify Maintainer access.
   
3. **Bitbucket:** confirm Admin access.
   

In every case, read the Vercel Activity log directly, because it often records a failure reason that never makes it to the project dashboard.

## The Ignored Build Step skips deploys on purpose

When the rest of the pipeline is healthy and a deployment is still missing, the cause is frequently an Ignored Build Step doing exactly what it was configured to do. The trap is the exit code convention, which inverts the standard Unix meaning. The Ignored Build Step is a user-defined script that decides whether a commit should produce a deployment: a return code of `0` skips the build, and a code of `1` or greater builds a new deployment. A script written under normal Unix conventions, where `0` means success, will therefore skip every commit on every branch.

Three scenarios tend to create the appearance of a broken pipeline.

### Scenario one: a stale diff baseline

The Ignored Build Step compares the new commit against the previous commit on the branch, not against the last successful deployment. In a monorepo where the latest commit changed files in `/api`, the frontend project's build is skipped because no frontend files changed. If a content management system (CMS) update then fires a deploy hook, that deployment is skipped too, because the last code change lived in a different part of the monorepo, and subsequent deploy hook calls keep skipping until a new commit touches the frontend path.

### Scenario two: feature-branch commits that appear to vanish

If commit 2a touches the frontend and commit 2b touches only the backend, 2b doesn't deploy the frontend project, because 2b is compared against 2a and the diff shows no frontend changes. Later frontend-only commits can also be skipped once the comparison baseline has drifted.

### Scenario three: inverted environment logic

This is the one that most resembles a broken webhook. A common Ignored Build Step checks `VERCEL_ENV` and proceeds only for production:

`if ["$VERCEL_ENV" == "production" ]; then exit 1; else exit 0; fi` If the exit code logic is accidentally reversed so the script returns `0` where the intent was to proceed, every commit on every branch skips silently, and the symptom is indistinguishable from a delivery failure. One more detail decides whether these scripts work at all: the Ignored Build Step runs in the context of the Root Directory, not the repository root. Paths have to be relative to the Root Directory, so if the Root Directory is `packages/web` and the script needs to watch `packages/docs`, the path is `../../packages/docs`. An incorrect path means the script never detects the changes it was written to catch. ### Skipping mechanisms have different resource costs Vercel offers two ways to filter deployments in a monorepo, and the difference between them shows up under concurrency pressure. The Ignored Build Step runs after a build slot is claimed, which means a canceled build still counts toward deployment quotas and concurrent build slots. The script executes inside the build environment, decides to skip, and releases the slot afterward. Vercel's automatic skipping of unaffected projects evaluates which projects a commit affects before claiming a slot, so it never occupies one. | Mechanism                    | When it evaluates        | Occupies a build slot                    | | ---------------------------- | ------------------------ | ---------------------------------------- | | Ignored Build Step           | After a slot is claimed  | Yes, counts toward quota and concurrency | | Skipping unaffected projects | Before a slot is claimed | No                                       | For a Hobby team with one concurrent build slot and a 100-deployment daily cap, that distinction decides whether skipped builds create queue pressure that delays real deployments. Automatic skipping has two requirements: the project must be connected to a GitHub repository, and the monorepo must use npm, yarn, pnpm, or Bun workspaces. For Turborepo projects, the recommended Ignored Build Step is a single command: `npx turbo-ignore --fallback=HEAD^1` This depends on `turbo.json` declaring the dependency graph correctly. If a shared package isn't declared as a dependency of the packages that consume it, `turbo-ignore` won't recognize that a change to the shared package should rebuild its dependents, and those dependents will skip silently when they should deploy. With automatic workspace scoping and a globally installed `turbo`, the build command can be as plain as `turbo build`, with the filter inferred from the configured Root Directory. Monorepos can also opt into Consolidated Commit Status for GitHub, which produces a single commit status on pull requests instead of one per project, so branch protection can be configured once and each project's settings declare which Vercel projects are required for merge. ## Deploying every commit is not the goal Some missing deployments aren't failures at all. They're the platform behaving as designed, and a deliberate skip produces the same symptom as a broken pipeline: a commit and nothing after it. Deployment frequency and release frequency are different metrics, and selective deployment is a supported optimization rather than a workaround. Three mechanisms exist specifically to support selective deployment as a performance choice: - **Ignored Build Step:** a user-defined script that decides whether a commit produces a deployment. The tradeoff is that it runs after a slot is claimed, so a skip still counts toward deployment quotas and concurrency.    - **Skipping unaffected projects:** evaluates which projects a commit affects before claiming a build slot, so skips are free. The tradeoff is that it requires a GitHub-connected project and a workspace-based monorepo, and its precision depends on the dependency graph being declared correctly.    - **SHA deduplication:** a commit SHA (hash) that was already deployed produces no new deployment. The tradeoff is that it keys on the SHA, so a force-push or rebase that rewrites history can defeat it.    The pattern they share is that a deploy gets skipped on purpose. Before treating a missing deployment as a failure, confirm it wasn't one of these mechanisms declining work that didn't need to run. ## Diagnostic checklist When a commit doesn't trigger a deployment, working through these steps in order eliminates the most common causes before the less likely ones. 1. Check the Git login connection in Account Settings, then Authentication. This is the most common cause and the fastest fix.     2. Verify the commit author has access to the Vercel team, and read the Activity log for any Vercel Bot comment explaining the failure.     3. Confirm the local `git config user.email` matches the email registered on the Git provider account, including any plus-address variations.     4. Check the production branch configuration in Project Settings, Git. A push to a non-production branch should still trigger a preview deployment, so confirm the branch name is exact.     5. Inspect GitHub repository settings and webhooks for a Vercel webhook. If none exists, disconnect and reconnect the repository.     6. Verify the repository is in the Vercel GitHub App's allowed list under GitHub Settings, Applications, Vercel, Repository Access.     If all six pass, the build filter is next: 1. Look for an Ignored Build Step in Project Settings, Git, and test the script locally with the same environment variables Vercel provides. Check the exit code of the last command with `echo $?`.     2. Check for `git.deploymentEnabled` set to `false` in `vercel.json`.     3. On a Hobby plan, check whether the 100-deployments-per-day limit has been reached. Repeatedly reconnecting and manually redeploying while troubleshooting can exhaust this limit on its own and reproduce the exact symptom under investigation.     ## Ship intentionally, not on every commit Reading a missing deployment as a silently rejected commit, rather than a broken pipeline, is what makes the checklist order itself. Most of these cases resolve at a single boundary, usually the authentication connection, and the ones that don't tend to be the platform optimizing on purpose. Once that framing is in place, the question shifts from why the pipeline is broken to which boundary said no, and that's a faster question to answer. The same reframe applies to Vercel's selective-deployment features once the search is over. Treated as obstacles, they look like the platform swallowing deploys. Treated as tools, they're the reason a monorepo team can push constantly without flooding the build queue, because unaffected projects never claim a slot and already-shipped SHAs never rebuild. To put the diagnostic order into practice, [deploy a new project](https://vercel.com/new) or browse the [templates](https://vercel.com/templates) to start from a working configuration.

## Frequently asked questions about Vercel deployments

### Why does the Vercel Bot not comment on my commit?

When the Vercel for Git integration is installed properly, the Bot leaves comments indicating success or failure. Comments don't appear when no deployment could be created at all, which happens when pre-deployment validation fails, for example, from an incorrectly formatted `vercel.json`. The absence of a Bot comment is itself a diagnostic signal that validation failed before the Bot could respond.

### Can I have two Vercel accounts connected to the same GitHub account?

No. When the link is set up on a second account, it's removed from the first. Identify which Vercel account should own the connection and reconnect from that account.

### Why did my deploy hook stop working in a monorepo?

Deploy hooks trigger a build using the latest commit on the branch. If the Ignored Build Step compares that commit against the previous one and finds no changes in the watched paths, the build is skipped. This happens when an unrelated commit, such as an API-only change, is pushed between deploy hook calls and resets the diff baseline.

### What's the difference between the Ignored Build Step and skipping unaffected projects?

The Ignored Build Step runs after a build slot is claimed and still counts toward deployment quotas and concurrent build limits. Automatic skipping of unaffected projects evaluates affected projects before claiming a slot and doesn't occupy one. For teams near their concurrency limits, automatic skipping avoids the queue pressure the Ignored Build Step creates.

### How many deployments can I run per day?

Hobby plans allow 100 deployments per day with 1 concurrent build. Pro plans allow 6,000 deployments per day, with 3 concurrent builds by default and up to 500 with on-demand concurrency enabled. Enterprise plans have custom limits.

| Plan       | Deployments per day | Concurrent builds                 |
| ---------- | ------------------- | --------------------------------- |
| Hobby      | 100                 | 1                                 |
| Pro        | 6,000               | 3 by default, up to 500 on-demand |
| Enterprise | Custom              | Custom                            |

Once a rate limit is hit, deployments resume after the limit window expires.

---

[View full KB sitemap](/kb/sitemap.md)
