# Git export sync

Source: https://docs.externa.qiick.io/docs/git-export

Optional **content-as-code** path: on **publish**, Externa can write published item files into a git worktree and push with a deploy key. For most headless sites, prefer [outbound webhooks](/docs/webhooks) → CI rebuild instead.

> **Related**
> [Webhook rebuild & CDN purge](/docs/webhook-rebuild-purge) · [Content versioning](/docs/content-versioning) · [Environment variables](/docs/environment-variables) · [Threat model](/docs/threat-model)

## When to use

| Need                         | Prefer                                  |
| ---------------------------- | --------------------------------------- |
| Rebuild Next/Nuxt/Astro      | Webhooks → deploy hook                  |
| Files in a docs/content repo | **Git export** (this page)              |
| One-off dump                 | `php artisan git-export:sync --dry-run` |

## Enable

```ini
GIT_EXPORT_ENABLED=true
GIT_EXPORT_REMOTE_URL=git@github.com:org/content.git
GIT_EXPORT_BRANCH=main
GIT_EXPORT_SSH_KEY_PATH=/var/externa/keys/content_deploy
GIT_EXPORT_FORMAT=json
GIT_EXPORT_DRY_RUN=false
GIT_EXPORT_COLLECTION_SLUGS=*
```

Queue a worker. Publishing a versioned item (`item.published`) queues `ExportCollectionItemToGitJob`.

The remote may be an empty bare repository: on first export Externa initializes the branch and pushes it ([#182](https://github.com/qiick-io/externa-core/issues/182)). Clones use `--template=`, so locked or sandboxed filesystems work ([#179](https://github.com/qiick-io/externa-core/issues/179)).

Full sync:

```bash
php artisan git-export:sync
php artisan git-export:sync --dry-run --collection=posts
```

## Layout

```text
content/{collection_slug}/{item_id}.json   # or .md when GIT_EXPORT_FORMAT=markdown
```

## Threat notes

- Use a **write-limited deploy key** for the content repo only — not your app monorepo.
- Keep the private key **on disk** (`GIT_EXPORT_SSH_KEY_PATH`); do not paste keys into Project settings or git.
- Start with `GIT_EXPORT_DRY_RUN=true` to verify commits without push.
- The worker host can push to the remote — treat that host as a secrets boundary.
- Bulk AI imports do **not** auto-export every row; run `git-export:sync` after large imports if needed.

## Out of scope

- Bidirectional sync / pull-from-git CMS
- PR-per-publish workflows
- Replacing webhooks for static host rebuilds
