Configure and run buf breaking
buf breaking compares a Protobuf schema against an earlier version and reports any rules that the newer version breaks. Every run takes two inputs: the current schema (your workspace, by default) and a baseline passed as --against or --against-registry.
buf breaking --against '.git#branch=main'A baseline can be a Git reference, a module on the Buf Schema Registry, a tarball, or a zip archive. This page covers how to configure rules and how to point buf breaking at each kind of baseline. For a first walk-through, see the quickstart. For every available rule, see the rules and categories page.
Configure in buf.yaml
Breaking change rules live in the buf.yaml file at the root of your workspace. With no configuration, buf breaking behaves as if this were written:
buf.yaml
version: v2
breaking:
use:
- FILEA complete configuration uses use, except, ignore, ignore_only, ignore_unstable_packages, and a list of plugins:
buf.yaml
version: v2
breaking:
use:
- FILE
except:
- RPC_NO_DELETE
ignore:
- foo/bar.proto
ignore_only:
FIELD_SAME_JSON_NAME:
- baz
ignore_unstable_packages: true
plugins:
- plugin: buf-plugin-fooSee the buf.yaml reference for the full shape of the breaking block, and rules and categories for the rules that ship with the Buf CLI.
Choose a baseline to compare against
buf breaking needs a baseline to diff against. Pass it as --against <input>, where <input> is a Buf input: a Git reference, a BSR module, or an archive. To compare every named module in your workspace against its latest published version on the BSR, use --against-registry instead.
Local Git repository
Compare your working tree against a branch, tag, or commit in the local Git repository:
buf breaking --against '.git#branch=main'
buf breaking --against '.git#tag=v1.0.0'This is the common shape when iterating on a schema locally. See the Git input reference for every available option.
Remote Git repository
Many CI services, including GitHub Actions, run shallow clones that don’t include the branches you want to diff against. Point buf breaking at the remote URL and the Buf CLI clones only the single commit it needs, so this stays fast even on large repositories:
buf breaking --against 'https://github.com/acme/petapis.git'For repositories that require authentication, see HTTPS authentication and SSH authentication.
Subdirectory within a repository
If your buf.yaml lives in a subdirectory, include subdir= in the input:
buf breaking --against '.git#tag=v1.0.0,subdir=proto'Module on the Buf Schema Registry
Compare a single module against its latest published version:
buf breaking --against buf.build/acme/petapisTo compare every module in your workspace at once, use --against-registry:
buf breaking --against-registry--against-registry is the preferred form when every module in the workspace has a name, and errors if any module is missing one.
Archive (.tar.gz or .zip)
buf breaking accepts tarballs and zip archives. This is convenient for GitHub, which serves an archive for any commit or branch:
buf breaking --against "https://github.com/acme/petapis/archive/${COMMIT}.tar.gz#strip_components=1"
buf breaking --against "https://github.com/acme/petapis/archive/${COMMIT}.zip#strip_components=1"Narrow the check to specific files
By default, buf breaking checks every file in the workspace. Use --path to restrict the check to specific files:
buf breaking --against '.git#branch=main' --path path/to/foo.proto --path path/to/bar.protoThis is an advanced option, intended for editor or Bazel integrations. In most cases, letting buf breaking discover files itself produces better results, especially when using the FILE category.
Format output as JSON
Output defaults to one violation per line. Pass --error-format=json to emit each violation as a JSON object, suitable for piping into jq or other tools:
buf breaking --against '.git#branch=main' --error-format=json | jq .
{
"path":"acme/pet/v1/pet.proto",
"start_line":18,
"start_column":3,
"end_line":18,
"end_column":9,
"type":"FIELD_SAME_TYPE",
"message":"Field \"1\" on message \"Pet\" changed type from \"enum\" to \"string\"."
}Plugins and policies
Rules can come from Buf plugins in addition to the built-ins. To use a plugin, install it (ideally on your $PATH) and list it under plugins in buf.yaml. Its rules and categories then mix with the built-ins under use, except, ignore, and ignore_only:
buf.yaml
version: v2
breaking:
use:
- FILE
- CATEGORY_ID_FROM_PLUGIN
except:
- RULE_ID_FROM_PLUGIN
plugins:
- plugin: buf-plugin-fooIf a plugin rule has default: true and the breaking block doesn’t list any of the plugin’s rules or categories, that rule runs automatically.
Run buf config ls-breaking-rules to list every rule active in the current workspace, including rules contributed by plugins.
To share a set of breaking-change rules across multiple workspaces, use Buf policies.
Run in CI
buf breaking is built for CI pipelines. For setup, see CI/CD setup and the GitHub Actions guide.