DEV Community

Cover image for How Do You Version-Control an OpenAPI Spec With Git?
Hassann
Hassann

Posted on • Originally published at apidog.com

How Do You Version-Control an OpenAPI Spec With Git?

Your OpenAPI spec is a contract. When it drifts, clients break, mocks go stale, and tests can pass against an API that no longer exists. Treat the spec like production code: put it in Git, branch it, review it, and validate it on every change.

Try Apidog today

This guide shows how to version-control OpenAPI with Git in a practical workflow: where to store the file, how to branch, what to review in a spec diff, how to validate changes in CI, and how to commit and push changes from Apidog.

Why version-control your OpenAPI spec

A spec stored in a wiki or shared drive has no reliable history. You cannot easily see who changed the POST /orders payload, why it changed, or how to roll it back.

Put openapi.yaml under version control and you get:

  • History: every change is a commit with an author, timestamp, and message.
  • Blame: git blame openapi.yaml shows who added a field and when.
  • Rollback: revert a bad commit if a contract change breaks clients.
  • Review: spec changes go through pull requests before they reach main.

This is the foundation of a Git-native API workflow: the spec is source code, and source code belongs in Git.

Where to put the OpenAPI file

Keep the location predictable. For a single API version, use either the repo root or an api/ directory:

my-service/
├── api/
│   └── openapi.yaml
├── src/
└── README.md
Enter fullscreen mode Exit fullscreen mode

For most teams, this is enough:

api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

If you maintain multiple major versions in parallel, split by version:

api/
├── api-v1.yaml
└── api-v2.yaml
Enter fullscreen mode Exit fullscreen mode

Use this structure when v1 must stay stable for existing clients while v2 evolves.

Benefits of version-specific files:

  • Breaking changes stay isolated.
  • Diffs are smaller.
  • Reviewers know which contract is changing.
  • CI can validate each version independently.

This is the core idea behind API spec as code: your API contract should be stored, reviewed, and shipped like code.

Pick one convention and document it in your repo. Avoid having multiple files that all claim to be the canonical spec.

Branching strategy for OpenAPI changes

You do not need a special branching model for API specs. Reuse your existing Git workflow:

  1. Branch from main.
  2. Change the spec.
  3. Validate locally.
  4. Open a pull request.
  5. Review and merge.

A clear branch naming convention helps reviewers spot contract changes quickly:

Branch type Pattern Example
New endpoint api/add-<resource> api/add-refunds
Field change api/change-<resource>-<field> api/change-order-status
Breaking change api/breaking-<description> api/breaking-v2-auth
Fix / cleanup api/fix-<description> api/fix-pagination-schema

The api/ prefix makes API contract changes easy to filter in pull requests and CI.

For breaking changes, use an explicit breaking- prefix. That signals that the PR may require:

  • a major version bump,
  • migration notes,
  • client communication,
  • additional review.

Keep spec branches short-lived. A branch that stays open for weeks is more likely to conflict with other contract changes.

Make OpenAPI diffs easy to review

A spec PR is a contract change. Reviewers should be able to read the diff without fighting formatting noise.

Write YAML consistently:

paths:
  /orders/{orderId}:
    get:
      summary: Get an order
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Order found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
Enter fullscreen mode Exit fullscreen mode

Use these formatting rules:

  • consistent indentation,
  • one property per line,
  • stable ordering for paths and schemas,
  • descriptive operation summaries,
  • no unnecessary reformatting in unrelated sections.

A one-field change should look like a one-field diff.

What to review in a spec PR

When reviewing an OpenAPI pull request, check the contract impact first.

1. Breaking changes

Look for changes that can break existing clients:

  • added required request fields,
  • removed response fields,
  • renamed fields,
  • changed field types,
  • removed enum values,
  • changed path parameters,
  • changed authentication requirements.

Example breaking change:

components:
  schemas:
    CreateOrderRequest:
      type: object
      required:
        - customerId
        - shippingAddress
        - couponCode # New required field: breaking
Enter fullscreen mode Exit fullscreen mode

Adding couponCode as required breaks clients that do not send it.

Prefer a backward-compatible shape:

components:
  schemas:
    CreateOrderRequest:
      type: object
      required:
        - customerId
        - shippingAddress
      properties:
        couponCode:
          type: string
          description: Optional coupon code.
Enter fullscreen mode Exit fullscreen mode

2. Backward compatibility

Usually safe:

  • adding a new endpoint,
  • adding an optional request field,
  • adding a response field,
  • adding a new enum value if clients are designed to handle unknown values.

Risky or breaking:

  • removing fields,
  • changing field types,
  • making optional fields required,
  • changing response status codes,
  • narrowing accepted input.

3. Naming consistency

Check whether the new endpoint follows the rest of the API:

GET /orders
GET /orders/{orderId}
POST /orders
Enter fullscreen mode Exit fullscreen mode

Avoid introducing inconsistent patterns like:

GET /order-list
GET /getOrderById
Enter fullscreen mode Exit fullscreen mode

4. Completeness

Every new operation should include:

  • summary,
  • request schema if applicable,
  • response schemas,
  • error responses,
  • examples where useful,
  • authentication requirements if applicable.

Example:

paths:
  /refunds:
    post:
      summary: Create a refund
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateRefundRequest"
      responses:
        "201":
          description: Refund created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Refund"
        "400":
          description: Invalid refund request
        "401":
          description: Unauthorized
Enter fullscreen mode Exit fullscreen mode

5. Examples

Examples make docs, mocks, and tests more useful.

components:
  schemas:
    Refund:
      type: object
      properties:
        id:
          type: string
          example: "ref_123"
        orderId:
          type: string
          example: "ord_456"
        amount:
          type: integer
          example: 2500
        currency:
          type: string
          example: "USD"
        status:
          type: string
          example: "pending"
Enter fullscreen mode Exit fullscreen mode

Do not rely only on manual review for breaking changes. Add CI checks that compare the PR spec against main and fail when incompatible changes are detected.

Commit and push from Apidog

Editing YAML by hand works, but a visual editor with live validation can catch mistakes earlier.

Apidog’s Spec-First Mode supports two-way Git sync: you can edit the spec in the UI, commit changes, push to your repo, and pull teammate changes back into Apidog.

A practical workflow:

  1. Connect your Git repo.
  2. Point Apidog to the OpenAPI file, such as api/openapi.yaml.
  3. Edit endpoints, schemas, parameters, and examples in the visual editor.
  4. Let Apidog write the updated YAML back to the file.
  5. Commit on a branch.
  6. Push the branch.
  7. Open a pull request in your Git provider.

Apidog Spec-First Mode

Because Apidog serializes YAML consistently, diffs stay smaller and easier to review. You avoid noisy reordering or unrelated reformatting.

Read the setup guide in the Apidog Spec-First Mode docs. If you want to sync to a specific Git provider, see syncing your OpenAPI spec to GitHub.

Validate OpenAPI changes in CI

Never let an invalid spec reach main. Add validation to your pull-request checks.

A minimal GitHub Actions workflow using Redocly CLI:

name: Validate OpenAPI

on:
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Lint OpenAPI spec
        run: npx @redocly/cli lint api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

This catches structural and style issues before merge.

You can also validate multiple spec files:

name: Validate OpenAPI

on:
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Lint API v1
        run: npx @redocly/cli lint api/api-v1.yaml

      - name: Lint API v2
        run: npx @redocly/cli lint api/api-v2.yaml
Enter fullscreen mode Exit fullscreen mode

Detect breaking changes automatically

Linting verifies that the spec is valid. It does not always tell you whether the change is safe for existing clients.

Add a diff step that compares the PR version against main.

Example using oasdiff:

name: OpenAPI Breaking Change Check

on:
  pull_request:

jobs:
  breaking-changes:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install oasdiff
        run: |
          curl -fsSL https://raw.githubusercontent.com/Tufin/oasdiff/main/install.sh | sh

      - name: Check for breaking changes
        run: |
          git show origin/main:api/openapi.yaml > /tmp/openapi-main.yaml
          oasdiff breaking /tmp/openapi-main.yaml api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

This kind of check can catch:

  • removed fields,
  • new required parameters,
  • changed schema types,
  • removed endpoints,
  • changed response contracts.

Humans can miss these in a large diff. CI should not.

Best practices for OpenAPI version control

Use these habits to keep your spec workflow reliable.

Use semantic versioning

Update info.version when the contract changes.

info:
  title: Orders API
  version: 2.1.0
Enter fullscreen mode Exit fullscreen mode

A common convention:

  • breaking change → major version bump,
  • backward-compatible feature → minor version bump,
  • documentation or non-contract fix → patch version bump.

Keep a changelog

Add a CHANGELOG.md next to the spec:

api/
├── openapi.yaml
└── CHANGELOG.md
Enter fullscreen mode Exit fullscreen mode

Example entry:

## 2.1.0

- Added `GET /refunds/{refundId}`.
- Added optional `refundReason` field to refund responses.
- Updated examples for refund creation.
Enter fullscreen mode Exit fullscreen mode

Keep PRs small

One logical API change per PR.

Good:

Add refund creation endpoint
Enter fullscreen mode Exit fullscreen mode

Avoid:

Update refunds, orders, auth, pagination, and examples
Enter fullscreen mode Exit fullscreen mode

Large spec PRs make breaking changes harder to spot.

Write descriptive commit messages

Use messages that explain the contract change:

Add refundReason to refund request schema
Enter fullscreen mode Exit fullscreen mode

Avoid:

update spec
Enter fullscreen mode Exit fullscreen mode

Never edit main directly

Even small changes should go through a branch and PR. This keeps history, review, and CI consistent.

FAQ

How do I detect breaking changes in an OpenAPI spec?

Run a spec-diff tool in CI that compares the pull request spec against the version on main.

Tools like oasdiff can classify changes as breaking, non-breaking, or unclassified, then fail the build when a breaking change is detected.

This helps catch removed fields, new required parameters, changed types, and removed endpoints.

Should I keep one OpenAPI file or split it across many?

Start with one openapi.yaml. It is easier to review, validate, and version.

Split only when you need to:

  • maintain multiple major versions, such as api-v1.yaml and api-v2.yaml,
  • reduce a very large file,
  • reuse schemas with $ref.

Do not split too early. One readable file is often better than several fragmented files.

Can I version-control my spec without writing YAML by hand?

Yes. Apidog’s Spec-First Mode lets you edit the spec in a visual editor and sync changes to Git in both directions.

You still get:

  • Git history,
  • branches,
  • pull requests,
  • CI validation,
  • readable YAML diffs.

Top comments (0)