Lesstep
Bitbucket Cloud · Pipelines · Checked November 2, 2026

Bitbucket Pipelines: a step skipped by condition: changesets

A step with condition: changesets: runs only when the changed files match its patterns. When they don't, Pipelines marks the step Skipped, not failed, and the pipeline goes on (Atlassian's Dynamic step conditions). The surprises come from which changes Pipelines counts.

- step:
    name: Test API
    condition:
      changesets:
        includePaths:
          - "services/api/**"
    script:
      - cd services/api && npm test

Branch builds count the last commit only

Atlassian's Step options: in a pull-request pipeline all commits are taken into account; in every other pipeline, only the last commit. So when you push three commits at once and only the first one touched services/api/, the step above is skipped.

We made that branch with Git 2.53: one commit changing services/api/app.js, then one for docs/, then one for README.md. Comparing with the commit before gives only the last one:

$ git diff --name-only HEAD~1
README.md

The same page warns about the other side of this: a failing pipeline can turn green only because the failing step is skipped on the next run. A commit breaks the API tests, the step fails, the next commit changes only the docs, the step is skipped, and the pipeline shows green while the API is still broken.

Atlassian tracks the request to count every commit of a push as BCLOUD-20648, a suggestion from December 2020 that is still gathering interest. On its duplicate, BCLOUD-22212, the workaround given is to push commits one at a time.

Two more cases from the Dynamic step conditions page: on the first commit to a repository, every file counts as changed, and in a pull-request pipeline the comparison is with the destination branch.

Compare with main in a step of your own

For a feature branch, a first step can work out what changed since the branch left main and pass the answer on. Variable sharing carries the value to the next steps, and a state condition reads it:

pipelines:
  branches:
    'feature/*':
      - step:
          name: Detect changes
          script:
            - git fetch origin "+refs/heads/main:refs/remotes/origin/main"
            - |
              if git diff --name-only origin/main...HEAD | grep -q '^services/api/'; then
                echo "API_CHANGED=true" >> $BITBUCKET_PIPELINES_VARIABLES_PATH
              fi
          output-variables:
            - API_CHANGED
      - step:
          name: Test API
          condition:
            state: API_CHANGED == true
          script:
            - cd services/api && npm test

On the branch from our test, the three-dot diff listed all three files and the check set API_CHANGED=true. The git fetch line is there because the step's clone has no origin/main; if the branch left main more than 50 commits back, the diff stops with "no merge base" (Git commands that fail in a shallow clone).

Keep the check step out of a parallel block and without a condition of its own. Variables set in a parallel step are not passed to any later step, and a skipped step sets none, so the steps that read them see an empty value.

Patterns that never match

When the condition is checked

From Step options: for a step that starts on its own, when the step before it has finished. For a manual step with only changesets, when it is ready to start; with a state condition, when someone clicks Run or Deploy. A step with a retry strategy checks again on every retry. A halted step that is resumed does not.

What a skipped step leaves out

Per the Dynamic step conditions page, a skipped step uses no build minutes, produces no artifacts and sets no output variables. A later step that expects a file the skipped step would have built fails for a reason that has nothing to do with its own code.

Bitbucket Pipelines in IntelliJ IDEA

Pipeline Inbox for Bitbucket Pipelines, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the pipelines of all your Bitbucket Cloud repositories in an IDE tool window, with their steps, the failed step and the command it stopped at, and the step's log as Bitbucket writes it. The list, steps and logs are free; running, re-running and stopping pipelines are Pro (US$1.50 a month, with a 30-day trial).

Get it on JetBrains Marketplace

Atlassian, Bitbucket and Bitbucket Pipelines are trademarks of Atlassian; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with or endorsed by Atlassian or JetBrains.

More: Git LFS files that arrive as pointers, and LFS pushes from a step · Git commands that fail in a shallow clone (origin/main, git describe) · The scheduled pipeline did not run · "Container 'build' failed to pull image" · "Connection refused" to a service (MySQL, PostgreSQL, Redis) · "Not authorized to perform sts:AssumeRoleWithWebIdentity" (OIDC to AWS) · Test results not showing · A variable is empty · "Host key verification failed" (SSH) · "Cannot connect to the Docker daemon" · "authorization denied by plugin pipelines" (Docker) · "Container 'docker' exceeded memory limit." · Pipelines did not run after a push · "Container 'Build' exceeded memory limit." · "Exceeded build time limit of 120 minutes" · The cache is not used · "unexpected system error" · "command not found" · Submodules not cloned · "We couldn't clone the repository" · "No online runner available" · "No space left on device" · "Step exceeded processing limits" · The artifact is missing in the next step · The build passed before and fails now · Build setup takes too long · "You've run out of build minutes" · "Permission denied to update branch" · "You have reached your pull rate limit" (Docker Hub) · "There is an error in your bitbucket-pipelines.yml" · "This pipeline was paused" (deployments) · Parallel steps that keep running after one fails (fail-fast) · Bitbucket Pipelines plugins for IntelliJ IDEA, compared · 日本語