Skip to main content

Selective branch synchronization

By default, Infrahub creates an Infrahub branch for every new branch in a connected Git repository. When many of those Git branches are unrelated to Infrahub data, configure selective branch synchronization: a list of patterns that a Git branch name has to match before Infrahub imports it.

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, Infrahub imports and synchronizes every branch created in your Git repository, with no configuration required.

The one exception is an Infrahub branch with "sync with Git" turned off. Infrahub imports no commits into that branch from the Git branch of the same name, with or without rules.

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 with Git" option enabled will still synchronize to Git normally.

Infrahub applies the rules only when it creates new Infrahub branches from Git branches. When a rule matches the name of an Infrahub branch with "sync with Git" turned off, Infrahub still imports no commits into that branch.

Configuring selective synchronization​

Set the INFRAHUB_GIT_IMPORT_SYNC_BRANCH_NAMES environment variable (or the equivalent import_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.

[git]

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

# After — network/topology and similar branches are now imported
import_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.

[git]

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

# After — existing feature/* branches in Infrahub continue syncing
import_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, its "sync with Git" flag sets whether Infrahub imports commits into it: with the flag turned on, Infrahub keeps importing regardless of rule changes, and with the flag turned off, Infrahub imports nothing from Git.

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 for the next synchronization to complete. Infrahub starts one once a minute
  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 for the next synchronization to complete. Infrahub starts one once a minute
  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, the Tracked Ref Missing 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 Git state on the branch details page​

The details page of a branch other than the default branch has two cards that show the Git state of the branch and the tasks that ran on it. Open it from the branch name in the branches list, or from +N more in the Repositories column.

The Git repositories card lists every repository of the branch, with three columns:

  • Repository: the name of the repository
  • Git state: the sync status of the repository on the branch, such as In Sync or Import Error. A warning icon follows it when the operational status of the repository is Credential Error, Connectivity Error, or Error.
  • Commit: the commit of the repository on the branch

Below the table, the card names each repository whose import failed or whose operational status is an error:

  • A repository whose import failed on the branch, followed by import failed and the last error line of the failed import task, with a View task log → link. When Infrahub cannot find that line, the card says The error details couldn't be found for this import.
  • A repository whose operational status is Credential Error, Connectivity Error, or Error, followed by that status and the warning Infrahub can't fetch new commits, so the commit shown may be out of date. Check the repository's credentials and location.

The card shows three repositories this way; select Show all to list the others. When the branch does not sync with Git and has no repository to list, the card shows Not synchronised with Git.

The Tasks card lists the tasks that ran on the branch, such as imports, Generators, and validations. Select N failed to open the task list filtered to the failed tasks of the branch, including the tasks that ran again since. Select Open in Tasks to open the full task list of the branch.

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, because those are the branches Infrahub imports commits into. 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 Push to remote card on the details page of a read-write repository shows the push state. It shows the state of the default branch, whichever branch you selected. When no merge waits, it shows Nothing pending. Otherwise it shows:

  • Status: Pending or Action required
  • Cause, Required action, and Message from the remote, when the status is Action required
  • Pending merges: the merges that wait for the push

After an abandonment, the card also shows Last abandoned push, Abandoned by, Abandoned merges, and the Recorded commit, which is the commit that the default branch kept. To reimport on the default branch, select the Reimport current commit button of the card. The button is shown only when no push is pending. The other cards of the page do not list the nine attributes.

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 the Push to remote card shows, or that delivery_failure_cause and delivery_error hold, for example renew the credential or remove the branch protection.

  2. In the web interface, open the details page of the repository and select Retry push in the Actions menu. With GraphQL, 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. Infrahub starts a task at once: the web interface shows Retry of the pending pushes started., and the mutation returns the id of the task. Wait for the task to complete. After a successful push, the card shows Nothing pending, and 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. Check the pending merges, in the Push to remote card or in the entries of the delivery_queue value on the default branch. When you abandon, Infrahub drops every pending merge of the repository. You cannot abandon one merge and keep the others.

  2. In the web interface, select Abandon pending push in the Actions menu of the repository details page. The Abandon pending push dialog lists the merges that will not be pushed. Select Abandon to confirm. With GraphQL, 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.

The dialog sends the version of the queue that it lists. If a merge was added to or removed from the queue since that 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. In the web interface, Retry push and Abandon pending push are disabled with the reason Ask an administrator for access when you lack one of these permissions, and with Nothing to push when no merge waits.

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 for the next synchronization to complete. Infrahub starts one once a minute
  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

Infrahub imports no commits into a branch​

Possible cause:

  • The Infrahub branch has the "sync with Git" flag turned off. Infrahub imports no commits into such a branch, even when a Git branch of the same name exists and its name matches the rules. If Infrahub imported commits into the branch before you upgraded to Infrahub 1.12, the branch keeps the last commit imported. You cannot turn the flag on for an existing branch.

Solutions:

Infrahub imports the commits of this Git branch only into the Infrahub branch of the same name. For Infrahub to import the commits into another branch, merge the Git branch, in Git, into one of these branches:

  • The Git branch of an Infrahub branch that has the "sync with Git" flag turned on. When you create such a branch in Infrahub, Infrahub creates a Git branch of the same name and pushes it to the remote repository. After you merge into that Git branch, Infrahub imports the commits into the Infrahub branch at the next synchronization.
  • The Git branch set as the default_branch of the repository. Infrahub imports this Git branch into Infrahub's default branch.

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 with 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 import_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
  • Infrahub imports no commits into existing Infrahub branches with "sync with Git" turned off, whether or not the rules match them
  • 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​