> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracecat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspace Git sync

> Connect GitHub, GitLab, or Bitbucket to a workspace and see what a Git sync export writes to your repository.

Enterprise Edition

## Overview

Use Git sync to export workspace configuration to a repository you own as a pull request, then pull a reviewed commit into a workspace.

## Permissions

Organization admins configure providers. Workspace admins connect or change a workspace repository. Workspace editors can push and pull from an existing connection; viewers cannot sync.

For custom roles, provider setup requires `org:settings:update`, changing the workspace connection requires `workspace:update`, and the workspace Git sync page requires `workspace_sync:sync` to push and pull.

## Connect a provider

**1. Open organization Git providers**

Open `Git providers` in the organization sidebar (`/organization/vcs`).

![Organization Git providers with GitHub, GitLab, and Bitbucket connections](https://mintcdn.com/tracecat/5VxYc3hxgApGPNHY/img/manage-platform/git-sync-settings.jpg?fit=max\&auto=format\&n=5VxYc3hxgApGPNHY\&q=85\&s=5cbb1fd7454079537a0b63e2e3f3a86e)

**2. Connect your provider**

For GitHub, click `Connect`, then create a GitHub App through the manifest flow or enter the ID and private key of an existing GitHub App. Install it on the repositories you want to sync.

For GitLab, click `Connect`, then enter your base URL and a project or group access token with both `api` and `write_repository` scopes. Before upgrading an existing GitLab connection to durable Git sync, replace an `api`-only project or group token with one that has both scopes. The worker uses Git-over-HTTPS to push the reviewed commit and the API to manage merge requests. Personal access tokens with `api` already include Git write access; see [GitLab access token scopes](https://docs.gitlab.com/security/tokens/access_token_scopes/).

For Bitbucket, click `Connect` (or `Manage` for an existing connection) to choose Cloud or Data Center.

For Cloud, click `Connect`, then enter your Atlassian account email and a [scoped API token](https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/). Select all four [permissions](https://support.atlassian.com/bitbucket-cloud/docs/api-token-permissions/):

* `read:repository:bitbucket`
* `write:repository:bitbucket`
* `read:pullrequest:bitbucket`
* `write:pullrequest:bitbucket`

The account must have access to the repository. Initialize the repository with a commit before syncing. For Bitbucket Data Center, click `Connect` on the Data Center connection with your HTTPS instance URL and an [HTTP access token](https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html) granting repository write permission. Include any port and context path in the instance URL, such as `https://bitbucket.example.com:8443/bitbucket`.

Use `Update` to rotate the token before it expires. Deleting these credentials disconnects sync across the organization; it preserves workspace resources, repository branches, and custom-registry credentials.

## Bind a workspace

**1. Open workspace Git sync**

Open `Git sync` in the workspace sidebar, then choose a `Provider` configured by your organization admin.

**2. Connect the repository**

Paste the repository's SSH clone URL and click `Connect`. For GitHub, you can also choose a repository from the GitHub App installation list.

Use `git@github.com:example-org/example-repo.git`, `ssh://git@github.com/example-org/example-repo.git`, or `git+ssh://git@github.com/example-org/example-repo.git`. HTTPS repository URLs and bare paths such as `example-org/example-repo` are not accepted.

For Bitbucket Cloud, use `git@bitbucket.org:example-workspace/example-repo.git`. For Data Center, use `git+ssh://git@bitbucket.example.com/PROJECT/repository.git`. Its hostname must match the configured instance. Put the port and context path in the organization instance URL; Tracecat uses HTTPS with your HTTP access token for Git and API requests.

![Connect a repository with a GitLab provider and SSH clone URL](https://mintcdn.com/tracecat/5VxYc3hxgApGPNHY/img/manage-platform/git-sync-connect.jpg?fit=max\&auto=format\&n=5VxYc3hxgApGPNHY\&q=85\&s=7d31d690d1a29842338f86a8c6e445f4)

### Change the connection

Click `Edit` beside the repository name. Use `Branch` to choose the base branch for new exports and the commit list for pulls. A stored URL ending in `@branch` pins that branch; a URL without the suffix uses the repository default.

Click `Change` beside the repository to edit its SSH URL, then `Save`. Changing the repository or pinned branch clears the current previews. `Disconnect` stops push and pull until you connect a repository again; it preserves workspace and repository content.

![Repository connection editor with an SSH URL, branch selector, and disconnect action](https://mintcdn.com/tracecat/5VxYc3hxgApGPNHY/img/manage-platform/git-sync-edit-repository.jpg?fit=max\&auto=format\&n=5VxYc3hxgApGPNHY\&q=85\&s=5596ac7748c7dc30d587006ec60ca4cb)

## What an export contains

A full export writes `tracecat.json` and one directory per resource type: workflows, agent presets, skills, tables, case fields, case tags, case dropdowns, case durations, variables, and secret metadata. Tracecat excludes schedules.

Tracecat names each resource's folder or file after its current name: workflows after their title, agent presets and skills after their slug, variables and secret metadata after their environment and name, and other resources after their name. For example, `workflows/Triage-alerts/definition.yml`, `variables/prod/vendor_token.yml`, or `tables/indicators/table.yml`. The `id` field inside each file identifies the resource, so renaming a resource moves its file on the next push and pullers update the same resource in place. Case tags are the exception: every tag shares one `case_tags/_all.yml` file, listed under `tags`.

When two resources of one type share a name, the one that already holds the path keeps it, and Tracecat appends the `id` to the other: `workflows/Triage-alerts-wf_4f2a.../definition.yml`. If neither has been pushed yet, the resource with the lower `id` gets the plain name. A resource keeps its path, suffix included, until you rename it.

Tracecat writes the script of each `core.script.run_python` action to its own file in the workflow's `scripts/` folder, named after the action's ref: `workflows/Triage-alerts/scripts/enrich_ip.py`. The action in `definition.yml` keeps its other arguments and has no `script` key. An action with no script yet, such as an empty Python step in a draft, gets no file. Edit the `.py` file to change the script; a pull reads it back into the action. If you rename an action's `ref` in `definition.yml`, rename its script file too: a pull fails on any `.py` file in `scripts/` that matches no Python action, and names the file. Pushing a workflow deletes every file in its folder that Tracecat does not write, so keep your own notes outside `workflows/`.

Pulls still read scripts written inline in `definition.yml` by earlier versions, and an inline script wins over a file for the same action. Instances on earlier versions ignore script files: they import Python actions without their scripts, and their pushes can leave stale script files that fail later pulls.

Keep each `id` unique: a pull rejects two files with the same `id`, so duplicate a resource in Tracecat rather than by copying its folder. If two branches rename the same resource and both merge, the repository holds two copies with one `id`; push that resource from Tracecat to remove the extra copy.

Repositories pushed by earlier versions name each resource's path by `id`, such as `workflows/wf_4f2a.../definition.yml` or `case_tags/<id>.yml`, or keep one file per case tag. Pulls still read them, and the next push moves each resource it writes to its readable path, or into `case_tags/_all.yml`, and deletes the old file. A push of selected resources keeps every other tag already in `case_tags/_all.yml`. A full push replaces the file with your workspace's tags, so it deletes tags that exist only on the branch. Instances on earlier versions reject resources at readable paths and `case_tags/_all.yml`, and ignore workflow script files, so upgrade every Tracecat instance that uses a repository before you push to it.

Exports carry configuration, not data:

* Forms export as a [`form:` block](https://docs.tracecat.com/automations/triggers/forms#git-sync) in their workflow's `definition.yml`, with no submissions.
* Tables export their column schema and no rows.
* Variables export key names and no values.
* Secrets export metadata only; a secret file with a `value` or `values` key fails import.
  [AWS-backed secrets](https://docs.tracecat.com/automations/core-concepts/external-secret-stores.md) also export
  their store name, secret name or ARN, and key mapping. If the target workspace
  has no authorized store with that name, the pull preview asks you to choose one.
  The choice applies to every secret that uses that store name.

## Related pages

* See [Push and pull](https://docs.tracecat.com/gitops/push-and-pull.md) for exporting a workspace as a pull request and pulling a reviewed commit.
* See [Security architecture](https://docs.tracecat.com/security/architecture.md#workspace-gitops) for the GitOps model and how registry versions resolve after a pull.
* See [Custom registry](https://docs.tracecat.com/custom-actions/custom-registry.md) for syncing custom actions into the registry, which is separate from workspace Git sync.
* See [Roles and permissions](https://docs.tracecat.com/manage-platform/rbac.md) for the scopes that gate connecting, exporting, and pulling.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.