Skip to main content

Work with branches

Branches in Infrahub provide isolated workspaces where you can make changes without affecting the main branch. This guide shows you how to create, manage, and delete branches using the GraphQL API, UI, or SDK.

Prerequisites

Before working with branches, ensure you have:
  • Access to an Infrahub instance
  • Appropriate permissions to create and manage branches
  • GraphQL API access or SDK installed (if using programmatic methods)

Create a branch

Branches are always created from the main branch. You can create a branch with data-only changes or one that synchronizes with Git repositories.

Using GraphQL

Create a branch using the BranchCreate mutation:
mutation {
  BranchCreate(
    data: {
      name: "feature-network-redesign"
      description: "Redesigning the core network topology"
      sync_with_git: true
    }
  ) {
    ok
    object {
      id
      name
      description
      status
      origin_branch
      branched_from
      is_default
      sync_with_git
    }
  }
}
Parameters:
  • name (required): Branch name following Git ref standards (3-250 characters)
  • description (optional): Human-readable description of the branch purpose
  • sync_with_git (optional, default: true): Whether to synchronize with Git repositories
  • origin_branch (optional): Must be main (currently the only supported value)
  • branched_from (optional): Timestamp to branch from (defaults to current time)

Using the Python SDK

from infrahub_sdk import InfrahubClient

client = InfrahubClient()

# Create a full branch (syncs with Git)
branch = await client.branch.create(
    branch_name="feature-network-redesign",
    description="Redesigning the core network topology",
    sync_with_git=True
)

print(f"Branch created: {branch.name}")
print(f"Status: {branch.status}")
print(f"Branched from: {branch.branched_from}")

Branch naming rules

Branch names must follow Git ref standards and cannot contain:
  • /. (path component starting with dot)
  • .. (double dots)
  • Leading / (cannot start with slash)
  • // (double slashes)
  • @{ (at-brace sequence)
  • \\ (backslashes)
  • Disallowed ASCII characters (control characters, ~^:?*[])
  • .lock suffix
  • Trailing / or .
The only exception is the global branch named __GLOBAL__. Valid names:
  • feature-add-devices
  • fix/datacenter-connectivity
  • experiment_new_schema
Invalid names:
  • feature..fix (contains ..)
  • fix/ (ends with /)
  • branch.lock (ends with .lock)
  • /feature (starts with /)

View branch details

Retrieve information about a specific branch or list all branches.

Query a single branch

query {
  Branch(name: "feature-network-redesign") {
    id
    name
    description
    status
    origin_branch
    branched_from
    created_at
    is_default
    is_protected
    sync_with_git
    schema_changed_at
  }
}

List all branches

query {
  Branch {
    edges {
      node {
        id
        name
        description
        status
        created_at
        sync_with_git
      }
    }
  }
}

Using the Python SDK

# Get a specific branch
branch = await client.branch.get("feature-network-redesign")

# List all branches
branches = await client.branch.all()
for branch in branches:
    print(f"{branch.name}: {branch.status}")

Update a branch

Update the description of an existing branch:
mutation {
  BranchUpdate(
    data: {
      name: "feature-network-redesign"
      description: "Updated description for network redesign"
    }
  ) {
    ok
  }
}
Note: Only the description field can be updated after branch creation. The branch name and other properties are immutable.

Delete a branch

Delete a branch when it’s no longer needed. You cannot delete the default branch (main) or the global branch.

Using GraphQL

mutation {
  BranchDelete(
    data: {
      name: "feature-network-redesign"
    }
    wait_until_completion: true
  ) {
    ok
  }
}
Parameters:
  • wait_until_completion (optional, default: true): Whether to wait for deletion to complete
If wait_until_completion is false, the mutation returns a task ID:
mutation {
  BranchDelete(
    data: { name: "feature-network-redesign" }
    wait_until_completion: false
  ) {
    ok
    task {
      id
    }
  }
}

Using the Python SDK

# Delete and wait for completion
await client.branch.delete("feature-network-redesign")

# Delete asynchronously
task = await client.branch.delete(
    "feature-network-redesign",
    wait=False
)
print(f"Deletion task: {task.id}")

Work with data-only branches

Data-only branches (sync_with_git: false) isolate changes to Infrahub without affecting Git repositories. These are ideal for data corrections or updates that don’t require code changes.
mutation {
  BranchCreate(
    data: {
      name: "data-fix-device-ips"
      description: "Correcting IP addresses for edge devices"
      sync_with_git: false
    }
  ) {
    ok
    object {
      name
      sync_with_git
    }
  }
}
Data-only branches:
  • Do not create corresponding Git branches
  • Are not merged to Git repositories
  • Are ideal for quick data fixes and updates
  • Still maintain full version control and history

Verify branch creation

After creating a branch, verify it exists and has the expected properties:
query {
  Branch(name: "feature-network-redesign") {
    id
    name
    status
    origin_branch
    branched_from
  }
}
Expected response:
{
  "data": {
    "Branch": {
      "id": "<uuid>",
      "name": "feature-network-redesign",
      "status": "OPEN",
      "origin_branch": "main",
      "branched_from": "2026-03-02T10:30:00Z"
    }
  }
}

Branch status values

Branches can have the following status values:
  • OPEN: Branch is active and ready for changes
  • NEED_REBASE: Branch needs to be rebased with the main branch
  • NEED_UPGRADE_REBASE: Branch requires migration before it can be used
  • DELETING: Branch is being deleted
See the Branch model for implementation details at backend/infrahub/core/branch/models.py:33.

Common patterns

Create a branch for a specific feature

mutation {
  BranchCreate(
    data: {
      name: "feature-add-bgp-peers"
      description: "Adding BGP peering configuration for datacenter routers"
      sync_with_git: true
    }
  ) {
    ok
    object {
      name
      status
    }
  }
}

Create a branch for experimentation

mutation {
  BranchCreate(
    data: {
      name: "experiment-new-vlan-design"
      description: "Testing new VLAN allocation strategy"
      sync_with_git: false
    }
  ) {
    ok
    object {
      name
    }
  }
}

Build docs developers (and LLMs) love