Skip to main content

Selective branch synchronization

Infrahub automatically creates all branches from a connected Git repository by default. While this ensures full visibility, it can create unnecessary noise when many Git branches are unrelated to Infrahub data or workflows. Selective branch synchronization introduces an optional configuration that allows teams to control which Git branches are imported and synchronized into Infrahub based on custom naming patterns.

Why selective synchronization matters​

In real-world Git repositories, teams often maintain many branches for different purposes:

  • Development branches for features unrelated to infrastructure
  • Documentation-only branches
  • Experimental work that doesn't involve Infrahub data
  • Personal development branches
  • Archive branches kept for historical reference

When all these branches automatically sync to Infrahub, it creates:

  • Visual clutter: Branch lists become difficult to navigate with irrelevant entries
  • Performance overhead: Unnecessary synchronization consumes system resources
  • Workflow confusion: Team members may struggle to identify which branches contain infrastructure changes

Selective synchronization addresses these challenges by allowing administrators to define explicit rules for which branches should be imported and maintained in Infrahub.

How selective synchronization works​

The feature operates through a set of branch naming rules that determine which Git branches Infrahub will track and synchronize.

Default behavior​

By default, every branch created in your Git repository continues to be automatically imported and synchronized into Infrahub. No configuration changes are required for teams who want to maintain the current behavior.

This default ensures backward compatibility and zero-configuration operation for existing deployments.

Enabling selective synchronization​

When you enable selective branch synchronization, Infrahub will only import branches whose names match a set of user-defined rules. Each rule is a regular expression that defines a pattern for matching branch names.

info

Selective synchronization only affects the Git to Infrahub direction. Branches created in Infrahub with the "sync to Git" option enabled will still synchronize to Git normally.

Configuring selective synchronization​

Set the INFRAHUB_GIT_IMPORT_SYNC_BRANCH_NAMES environment variable (or the equivalent sync_branch_names key in infrahub.toml) to a JSON array of regular expression patterns:

INFRAHUB_GIT_IMPORT_SYNC_BRANCH_NAMES=["^infra/.*$","^feature/infrahub-.*$"]

A configuration change requires a restart of the Infrahub server. For detailed instructions on applying configuration changes to your deployment, see How to configure Infrahub.

How to configure Infrahub../deploy-manage/install-configure/configure-infrahub
Validation

After setting those variables and restarting, branch synchronization will follow the defined rules.

Rule processing​

Infrahub processes the rules in the order they appear in the configuration. The first matching expression determines whether a branch is synchronized.

Processing logic:

  1. When Infrahub discovers a branch in the Git repository, it evaluates the branch name against each rule in sequence
  2. The first rule that matches the branch name determines the outcome
  3. If a match is found, the branch will be created and synchronized in Infrahub
  4. If no match is found after checking all rules, the branch will be ignored

This top-to-bottom evaluation allows for fine-grained control over branch synchronization behavior.

Rule evaluation during updates​

When you modify the synchronization rules after a repository has been imported, Infrahub evaluates branches differently depending on their current state:

Adding patterns to expand scope:

If a Git branch exists but was not previously imported because it didn't match the old rules, and it now matches the updated rules, Infrahub will import that branch during the next synchronization cycle.

# Before
sync_branch_names = ["^infra/.*$"]

# After — network/topology and similar branches are now imported
sync_branch_names = [
"^infra/.*$",
"^network/.*$"
]

Removing patterns to restrict scope:

If a branch was already imported into Infrahub and has the "sync with Git" flag enabled, it will continue to synchronize even if it no longer matches the updated rules. This preserves existing work and prevents unexpected data loss.

# Before
sync_branch_names = [
"^infra/.*$",
"^feature/.*$"
]

# After — existing feature/* branches in Infrahub continue syncing
sync_branch_names = ["^infra/.*$"]

Cleaning up branches manually:

If you want to stop synchronizing branches that no longer match your rules:

  1. Navigate to Branches in the Infrahub UI
  2. Find the branch you want to remove and click the delete option
  3. Or delete branches programmatically via the API
Permanent deletion

Manually deleting branches in Infrahub is permanent. The deletion does not affect the corresponding Git branches, and they will not be re-imported because they no longer match your rules.

info

The synchronization rules only control initial import of branches from Git to Infrahub. Once a branch exists in Infrahub with Git synchronization enabled, it continues syncing regardless of rule changes.

Regular expression patterns​

Each rule uses standard regular expression syntax to define matching patterns. This approach provides maximum flexibility without enforcing a specific naming convention.

Common pattern elements you can use:

  • ^ - Match the beginning of the branch name
  • $ - Match the end of the branch name
  • .* - Match any characters (zero or more)
  • [a-z] - Match any lowercase letter
  • [0-9]+ - Match one or more digits
  • (feature|fix) - Match either "feature" or "fix"

Example 1: infrastructure-only branches​

Your team uses a naming convention where all infrastructure-related branches start with infra/.

Rule:

["^infra/.*$"]

Results:

Git Branch NameMatches Rule?Imported to Infrahub?
infra/network-update✅ Yes✅ Created in Infrahub
infra/add-devices✅ Yes✅ Created in Infrahub
docs/update-readme❌ No🚫 Not imported
feature/new-api❌ No🚫 Not imported

Example 2: multiple team prefixes​

Different teams use different prefixes for their infrastructure work.

Rules:

[
"^infra/.*$",
"^network/.*$",
"^config/.*$"
]

Results:

Git Branch NameMatches Rule?Imported to Infrahub?
infra/devices✅ Yes✅ Created in Infrahub
network/topology✅ Yes✅ Created in Infrahub
config/templates✅ Yes✅ Created in Infrahub
docs/architecture❌ No🚫 Not imported

Example 3: feature branches with issue numbers​

Your workflow includes Infrahub-related feature branches that reference issue numbers.

Rule:

["^feature/infrahub-[0-9]+.*$"]

Results:

Git Branch NameMatches Rule?Imported to Infrahub?
feature/infrahub-321✅ Yes✅ Created in Infrahub
feature/infrahub-123-network✅ Yes✅ Created in Infrahub
feature/api-update❌ No🚫 Not imported
feature/device-backup❌ No🚫 Not imported

Verifying the configuration​

To verify that the selective synchronization rules are working correctly, you need a Git repository connected to Infrahub. If you haven't connected a repository yet, see How to connect external Git repositories.

Test with branches that should NOT be imported​

  1. Create a branch in your Git repository that doesn't match your rules:
git checkout -b docs/update-readme
git push origin docs/update-readme
  1. Wait a few seconds for the synchronization cycle to complete
  2. Check the Infrahub UI or API — this branch should not appear in Infrahub

Test with branches that SHOULD be imported​

  1. Create a branch in your Git repository that matches your rules:
git checkout -b infra/network-update
git push origin infra/network-update
  1. Wait a few seconds for the synchronization cycle to complete
  2. Check the Infrahub UI or API — this branch should appear in Infrahub

Verify using the Infrahub UI​

  1. Navigate to the Branches section in the Infrahub UI
  2. Confirm that only branches matching your rules are displayed

Verify using the API​

Query the GraphQL API to list all branches:

query {
Branch {
edges {
node {
name
}
}
}
}

Only branches matching your configured rules should appear in the results.

Checking Git state from the branches list​

The Branches page shows the Git repositories on each branch next to the branch itself, so a failed import is visible without opening the branch or the repository. Each branch keeps a single row, and two columns follow Proposed Changes:

ColumnWhat it shows
RepositoriesThe branch's first repository, linking to the repository's page on that branch. A repository whose last import failed comes first, then any repository with an unknown status or no status, then any repository that is syncing, then the rest, each group in alphabetical order. Hover the name to read its Git state, the first seven characters of the branch's commit for that repository, and whether the repository is read-only. When the branch has not imported a commit of its own, the commit can be inherited or missing, as How values are resolved for each branch describes. When the branch has more repositories, +N more opens the branch, whose details page lists all of them.
Git stateThe worst sync status among the branch's repositories, with the label and color the schema defines for it, such as In Sync or Import Error. When the branch has several repositories, a count such as 1/3 gives how many of them share that status. Hover the count to see how many repositories have each status.

The repositories listed for a branch follow the same rule as the query in the next section. A read-write repository appears only on branches that sync with Git, while a read-only repository appears on every open branch.

When a branch has no repository to show, its Repositories cell shows one of the texts in the following table, and its Git state cell stays empty. The cell can also show:

  • a loading indicator, while the page is still reading the list of repositories, or while it is still reading the status of a repository and none of the repositories it has read so far lists the branch
  • only the N repositories could not be loaded notice described below, when the page read no repository that lists the branch and could not read the status of some repositories
Repositories cellShown on
Not synced with GitOne branch
No repositoriesOne branch
No permissionEvery branch
Could not load repositoriesEvery branch, or one branch

Each text has these causes:

  • Not synced with Git: the branch does not sync with Git, and no read-only repository lists it.
  • No repositories: the branch syncs with Git, but no repository lists it. This happens when:
    • no repository is connected to Infrahub
    • the branch is merged or being deleted
    • the branch was created after the page last read the repository status lists
  • No permission: your account cannot read the repositories' Git state. This happens when:
    • your account cannot view one of the two repository kinds (read-write or read-only), so the page cannot list the repositories
    • your account cannot view the status of any repository
  • Could not load repositories: hover the text to read the reason. This happens when:
    • the list of repositories could not be read, or holds more than 500 repositories: the text shows on every branch
    • a repository lists more than 500 branches, and the branches the page read for it do not include this one: the text shows on this branch only

When the page cannot read the status of some repositories but can read the others, the Repositories cell shows the repositories it read, followed by a notice such as 1 repository could not be loaded or 3 repositories could not be loaded. Hover the notice to read the name of each repository and the reason, or No permission when your account cannot view that repository's status. The notice shows on every branch, including branches that do not sync with Git, because the page cannot tell which branches a repository it could not read would list. The Git state column counts only the repositories the page read. While the page is still reading the status of other repositories, the Repositories cell also shows a loading indicator after the repositories it already read. The notice does not show on a branch whose Repositories cell shows Could not load repositories because a repository lists more than 500 branches: that cell shows only the text, and its hover text names the repository.

The Repositories cell of a recently created branch can show No repositories or Not synced with Git until the page reads the repository status lists again. When you open the page or return to its window, the page reads the status lists again if it last read them more than a minute ago. It reads them at once when you select the reload button next to the Branches title. Creating or deleting a branch in the web interface also starts a new read. Merging or rebasing a branch from its details page runs as a background task. The status lists are read again when the task starts and again when it finishes, as long as the branch details page stays open and the task finishes before the page stops checking it, after 360 checks (about 30 minutes). A merge that deletes the branch opens the branches list at once. The branches list then reads the status lists again when the merge task finishes, under the same limit, as long as the branches list stays open. A branch that does not sync with Git and that no read-only repository lists keeps showing Not synced with Git.

The Branch, Status, Proposed Changes and date columns show as usual in every one of these states. While a repository is syncing, the page reads its Git state again until the sync finishes.

Checking a repository's status on every branch​

The branches list is organized by branch. To see what a single repository looks like from every branch at once, including the commit each branch resolves and whether its last import succeeded, use the InfrahubRepositoryBranchStatus query. It returns one row per branch and reads everything from the graph, so it does not contact a Git server or a task worker.

The id argument accepts the repository's ID or its name.

query RepositoryBranchStatus($id: String!, $limit: Int, $offset: Int, $syncStatus: String) {
InfrahubRepositoryBranchStatus(
id: $id
limit: $limit
offset: $offset
sync_status__value: $syncStatus
) {
count
edges {
node {
name { value }
status { value }
is_default { value }
sync_with_git { value }
branched_from { value }
commit { value updated_at }
sync_status { value label color }
internal_status { value label color }
ref { value }
}
node_metadata { created_at updated_at }
}
}
}

Which branches appear depends on the repository type. A read-write repository returns only branches with sync_with_git set to true, which is the same set the rules on this page control. A read-only repository returns every branch, because it tracks a single reference and is not affected by selective synchronization. In both cases, merged and deleting branches are left out, and the branch you send the query to does not change the result.

How values are resolved for each branch​

A branch that has never imported the repository still gets a row, and that row is not an error. An isolated branch, which is what a branch created today is, inherits the values the default branch held at the point the branch was created. A branch created before isolation became the default reads the default branch as it stands now instead.

Values written when the repository was first added are visible on every branch, including branches that already existed, because Infrahub records them outside any single branch. A read-only repository's commit and ref are the exception: they are recorded on the branch the repository was created on, so they reach only that branch and the branches forked from it afterwards.

sync_status__value, internal_status__value, and own_values_only narrow the rows on the server, and count reflects them. Set own_values_only to true to keep only the branches holding their own commit rather than an inherited one: the branches that have imported the repository themselves, plus, for a read-only repository, the branch it was created on.

warning

On a row that inherits its values, updated_at is the time the default branch was written, not the time that branch last imported the repository. Do not present it as a last-import time. To find out whether a branch has imported the repository at all, use the own_values_only argument.

info

This query always reports the present. A request that includes an at query parameter is rejected, because the list of branches it builds its rows from has no historical form. For a point-in-time view, query the repository object directly.

Permission requirement​

The account running the query needs the view permission on the repository's kind, Core/Repository or Core/ReadOnlyRepository, with a decision that covers both the default branch and other branches. A single ALLOW_ALL grant satisfies this, and so does ALLOW_DEFAULT together with ALLOW_OTHER. Granting only one of the two is refused with an error rather than a shortened list of branches.

When a push to the remote fails​

When you merge a branch that syncs with Git, Infrahub merges the branch in its database first. A background task then merges the matching Git branch of each read-write repository and pushes the result to the remote. That push can fail after the merge in Infrahub is complete: the remote can be unreachable, a token can expire, a branch protection can refuse the push, or someone can rewrite the history of the remote branch. The merge in Infrahub stays complete, and Infrahub records the failure on the repository. You can then see which merges wait, fix the cause, and retry the push or abandon it.

How Infrahub pushes a merge​

Infrahub adds each merge that changes the files of a read-write repository to the push queue of that repository. The log of the merge task shows a line such as The merge of branch infra/vlan-update waits for its push to repository network-config. For a merge that changes only data, and no file of the repository, Infrahub pushes nothing.

Infrahub pushes the whole queue of a repository in one push. It fetches the remote, checks each queued merge against it, merges each queued commit in merge order onto the current head of the remote default branch, and pushes the result. With the default settings, Git fast-forwards when it can, as described in merging branches. When the push succeeds, Infrahub records the new commit on its default branch and removes the merges from the queue. If someone pushed a commit to the remote default branch since the last synchronization, Infrahub merges the queue onto that commit, and imports it too.

When the push fails:

  • If the cause can clear without a change on your side, such as an unreachable remote, Infrahub tries the push again after 30 seconds, 2 minutes and 5 minutes. The status of the repository stays Pending meanwhile.
  • If the last automatic retry fails, or if the cause needs a change on your side, the status becomes Action required. Infrahub tries to push the whole queue again when you retry it, or at the next merge into the same repository that Infrahub accepts.
  • If Infrahub refuses the queue because of a conflict, a removed source commit or a rewritten history, each later merge into the repository is blocked until you resolve the cause or abandon the queue. When the remote default branch has a commit that Infrahub has not recorded, as after a rewritten history, Infrahub refuses the merge itself, as described in what waits while a push is pending. Otherwise, Infrahub adds the merge to the same queue and refuses its push for the same cause.
  • If a task worker stops during a push, Infrahub starts the push again after about 15 minutes without progress. The synchronization of the repository checks for such a push every minute.

Read the push state of a repository​

Infrahub records the push state of a read-write repository in nine read-only attributes whose names start with delivery_. Read them on the default branch: on another branch, their value is an old copy. To read the push state with GraphQL, query the repository on the default branch:

query RepositoryPushState($name: String!) {
CoreRepository(name__value: $name) {
edges {
node {
id
delivery_status { value label }
delivery_failure_cause { value label }
delivery_error { value }
delivery_queue { value }
delivery_last_abandonment { value }
delivery_reverted { value }
}
}
}
}
AttributeWhat it holds
delivery_statusnone, or no value, when no merge waits. pending while a push runs, is about to run, or waits for an automatic retry. action-required when no automatic retry is planned.
delivery_failure_causeWhy the last push failed, as the next table describes.
delivery_errorThe message of the last failure, with credentials removed. When the remote refused the push, this is the remote's own text, such as the message of a pre-receive hook.
delivery_queueThe pending merges in merge order, in entries, each with its source_branch, its source_commit and the time of the merge (merged_at). It also holds the version of the queue, which an abandonment needs.
delivery_last_abandonmentThe record of the last abandonment.
delivery_revertedA pushed commit that a later rewrite of the remote default branch removed.

The other three attributes, delivery_held_regeneration, delivery_last_delivered_commit and delivery_progress, hold the regeneration that waits, the last pushed commit, and the times of the last push attempt.

In the web interface, the details page of the repository lists the nine attributes in the On this branch card when you select Extra. The card shows the values of the branch that you selected, so select the default branch first.

For each value of delivery_failure_cause, the following table gives its label, whether Infrahub retries the push by itself, and what you can do:

ValueLabelRetried automaticallyWhat to do
remote-unreachableRemote unreachableYesWait, or retry when the remote is reachable again.
remote-advancedRemote moved during the pushYesWait, or retry.
record-failedPushed, not recordedYesWait, or retry. The remote can already have the content.
import-interruptedImport of the delivered commit was interruptedYesWait, or retry when the database, the Infrahub server and the remote are reachable. The remote already has the content.
not-foundRepository not found on the remoteNoCheck the location of the repository, and that the credential can see it, then retry.
certificateCertificate verification failedNoFix the certificate configuration, then retry.
credentialsCredentials rejectedNoFix the credential, then retry.
permissionPush refused by the remoteNoGive the credential push permission, or lift the branch protection, then retry.
import-failedImport of the delivered commit failedNoFix the content on the remote, then retry.
replay-conflictA pending merge conflicts with the remoteNoMerge the source branch into the default branch on the remote manually, then retry. Or abandon.
source-discardedA source commit is no longer on the remoteNoAbandon.
destination-rewrittenThe remote branch history was rewrittenNoAbandon.
unclassifiedUnclassified failureNoRead the message, then retry or abandon.

For a conflict, a source commit that is no longer on the remote, or a rewritten history, Infrahub pushes nothing. A removed source commit or a rewritten history comes from a force push or a deleted branch on the remote, and a push would put the removed commits back on the remote. A conflict needs a resolution that only a person can make.

What waits while a push is pending​

While a repository has pending pushes, with delivery_status at pending or action-required, Infrahub does not import the remote default branch of that repository. An import of the default branch removes the repository objects, such as Transformations, Generator definitions and checks, that the imported commit does not contain. The remote does not contain the pending merges yet, so an import would remove the objects that they added.

  • The synchronization skips the remote default branch and the remote branches that the pending merges come from. Infrahub imports a commit pushed to the remote default branch in the meantime when the push succeeds, or at the first synchronization after the queue is empty. Other branches synchronize as usual.
  • A task worker that clones the repository again does not import its default branch.
  • Reimport current commit is refused on every branch, with the message Repository <name> has pending pushes; a reimport now would remove the objects they added. Retry or abandon the pending pushes first. If a merge enters the queue after Infrahub accepted the request, the import task fails with the same message.
  • If someone pushes to the remote default branch while pushes are pending, Infrahub refuses to merge a branch whose Git branch in that repository is at another commit than the default branch, for example a branch that changes files of the repository. The message starts with Unable to merge branch <branch>, because Infrahub has not recorded the latest commit of branch <default branch> of repository <name>. Infrahub refuses before the merge, so the branch stays open. Retry the pending pushes, then merge the branch again after the push succeeds. After an abandonment, merge again after the next synchronization imports the remote default branch.
  • Infrahub refuses to convert the repository to a read-only repository, and keeps refusing until the regeneration that waited for the push has run.

The regeneration that the repository defines also waits: its artifact definitions, its Generator definitions, and the computed attributes that its Python Transformations calculate. After the merge, they would use the files of the repository from before the merge. Infrahub runs them once, after the push succeeds or after you abandon the pending pushes. The regeneration that other repositories define runs at once.

Retry the pending pushes​

Retry after you fix the cause, or when you do not want to wait for the next automatic retry.

  1. Fix the cause that delivery_failure_cause and delivery_error show, for example renew the credential or lift the branch protection.

  2. Send the InfrahubRepositoryDeliveryRetry mutation on the default branch, with the id of the repository:

    mutation RetryPush($id: String!) {
    InfrahubRepositoryDeliveryRetry(data: { id: $id }) {
    ok
    task { id }
    }
    }
  3. The mutation returns the id of the task at once. Wait for the task to complete. After a successful push, delivery_status is none.

If the push fails again for a cause that can clear by itself, the task retries it automatically, as after a merge.

Abandon the pending pushes​

Abandon the queue when the pending merges cannot reach the remote, for example after a rewrite of the remote history, or after a conflict that you do not want to resolve on the remote.

  1. Read the delivery_queue value of the repository on the default branch. Check the merges in entries: an abandonment drops every pending merge of the repository. You cannot abandon one merge and keep the others.

  2. Send the InfrahubRepositoryDeliveryAbandon mutation on the default branch, with the id of the repository and the version of the queue as queue_version:

    mutation AbandonPush($id: String!, $version: Int!) {
    InfrahubRepositoryDeliveryAbandon(data: { id: $id, queue_version: $version }) {
    ok
    task { id }
    }
    }
  3. The mutation returns the id of the task at once. Wait for the task to complete.

If a merge was added to or removed from the queue since you read the version, Infrahub refuses the request with The pending pushes of repository <name> changed since version <n>; reload and try again.

Both mutations need the update permission on repositories, such as object:Core:Repository:update:allow_all, and the global permissions manage_repositories and edit_default_branch (see permissions). Infrahub refuses a request on another branch than the default branch, with Send this request on the default branch <name>; the pending pushes live there. It also refuses both mutations for a read-only repository, for a staging repository, and when nothing is pending. An id that is not the id of a repository gets the same "not found" error as an unknown id. A push that runs, or an automatic retry that waits, does not block them: the task starts after the running push.

What an abandonment leaves behind​

An abandonment pushes nothing and imports nothing. After it:

  • The remote is unchanged. Infrahub removes nothing from it and deletes no remote branch.
  • The branches stay merged in Infrahub. The default branch keeps the repository objects that the abandoned merges added, although the remote does not have their files. If an import was still due, the default branch can also lack objects that its recorded commit holds.
  • delivery_last_abandonment holds the record of the abandonment: when, by whom, the abandoned merges, the version of the queue, and the commit that the default branch kept.
  • Infrahub runs the regeneration that waited, from the commit that the default branch kept. If that regeneration fails, the abandonment task fails, and Infrahub runs the regeneration again after about 15 minutes. To regenerate before that, run the artifact definitions, the Generator definitions and the computed attributes of the repository manually, as the log of the task says.
  • Infrahub never adds an abandoned merge to the queue again.

To make the repository objects match the remote again, run Reimport current commit on the default branch, from the actions of the repository or with the InfrahubRepositoryProcess mutation. To get the abandoned changes to the remote, merge the source branch on the remote manually, or merge again the branch that Infrahub creates from a kept source branch, as the next section describes.

The source branch is kept until its merge is pushed​

With delete_branch_after_merge and delete_git_branch_after_merge enabled, Infrahub deletes the remote branch of a merged branch. While a merge from that branch waits in the push queue, Infrahub keeps the remote branch, because it holds the commit that the push needs, and logs a warning in the log of the branch deletion. After the push succeeds, Infrahub deletes the remote branch, unless another pending merge comes from it.

If you abandon the pending pushes, the remote branch stays. At the next synchronization, Infrahub imports it again as a new branch, unless your synchronization rules exclude its name. You can then merge that branch again, and Infrahub pushes the new merge.

Limitations of the push queue​

  • Infrahub stops a stalled fetch or push of the pending merges only on an HTTP or HTTPS remote. Over SSH, a stalled push or fetch keeps the repository locked until the connection ends, and a retry waits for it.
  • A branch created in Infrahub from the default branch while pushes are pending holds the objects of the pending merges, but its Git branch does not hold their files. When the synchronization imports that Git branch, it removes those objects on the branch, and a merge of the branch removes them from the default branch. Check delivery_status of the repository before you create a branch that syncs with Git.
  • If a Generator of the held regeneration never ends, Infrahub waits for it as long as the task worker runs, and no other task runs the held regeneration of the repository in that time.
  • If the task worker stops while it runs the held regeneration, and the task manager still shows the task as running, Infrahub runs the regeneration again only after the task manager marks the task as crashed.
  • If the synchronization does not process a change of the default_branch of a repository within seven days, for example because pushes stay pending that long, Infrahub reads the change as a rewrite of the remote history. It can then record in delivery_reverted a removed push that did not happen.

Troubleshooting​

Branches not appearing after configuration​

Possible causes:

  • Infrahub services haven't been restarted after configuration changes
  • Regular expression pattern doesn't match the branch name
  • Synchronization cycle hasn't completed yet

Solutions:

  1. Verify the configuration is correct
  2. Restart Infrahub services
  3. Wait 10–15 seconds for the next synchronization cycle
  4. Test your regex pattern using an online regex tester

Branches still appearing after adding rules​

Possible causes:

  • The branches were already imported before you configured the rules
  • Branches have the "sync with Git" flag enabled
  • An environment variable is overriding the configuration file

Solutions:

  1. Check if an environment variable is set and taking precedence
  2. Delete existing branches manually if needed — rules only control new imports, not existing branches

All branches are being imported despite rules​

Possible causes:

  • Configuration not loaded correctly
  • Services not restarted
  • Syntax error in the configuration

Solutions:

  1. Check Infrahub logs for configuration errors
  2. Verify the TOML syntax is correct
  3. Verify the JSON syntax is correct for environment variables
  4. Restart services after any configuration change

Current scope and limitations​

Directional behavior​

Selective branch synchronization only affects the Git → Infrahub direction:

  • Git branches that don't match the rules will not be imported into Infrahub
  • Branches created in Infrahub with the "sync to Git" option enabled will still synchronize to Git normally
  • This asymmetric behavior allows teams to use Infrahub as the source of truth while filtering incoming Git branches

Dynamic updates​

When you modify the sync_branch_names configuration:

  • New Git branches will be evaluated against the updated rules during the next synchronization
  • Git branches that now match the rules will be automatically imported
  • Existing Infrahub branches with Git synchronization enabled continue syncing regardless of rule changes
  • Branches no longer matching the rules will not be automatically removed from Infrahub
  • You must manually delete branches in Infrahub if they no longer align with your synchronization policy

Repository types​

Selective branch synchronization applies to standard read-write repositories that support full bidirectional integration. Read-only repositories track a single reference and are not affected by this configuration.

Further reading​