# Git import, export, and interop

Oak is designed to be easy to arrive at and easy to leave. This page covers every way code moves between Git and Oak.

| You want to… | Use |
|---|---|
| Bring a GitHub repo over, with nothing installed | [Import from GitHub on the web](#import-from-github-on-the-web) |
| Bring any Git repo over from the terminal | [`oak clone <git-url>`](#import-with-oak-clone) |
| Convert a Git checkout you already have | [`oak init` in place](#convert-a-checkout-in-place) |
| Start a repo from a folder in the browser | [Upload a folder](#upload-a-folder) |
| Get full history back out as Git | [`oak export`](#export-back-to-git) |
| Let Git tooling read an Oak repo | [`git clone …/.git`](#clone-an-oak-repo-with-git) |
| Keep a copy on GitHub, or run GitHub Actions | [GitHub mirror](#mirror-to-github) |

## Import from GitHub on the web

No CLI, no Git — oak.space clones and converts the repo on its servers.

1. **Connect GitHub, once:** under **Settings → GitHub**, choose **Connect GitHub** and install Oak's GitHub App on the repositories you want (all, or a selection). For importing, Oak asks only for **read** access and mints a short-lived, single-repo token for each import.
2. **Pick a repo:** the **Import from GitHub** panel on your dashboard lists the repositories your connection can see.
3. **Choose what to bring:** the **branch** to import and the **destination organization**; optionally a different name, public visibility, and collaborators to invite. Oak checks the name is free as you type.
4. **Import:** a progress page streams status and opens the new Oak repo when it's done.

The web importer brings the **one branch you choose** straight onto the server as `main` — there's nothing to push afterwards. Run `oak clone <org>/<repo>` (or [mount it](/docs/mounts)) to get a working copy.

## Import with oak clone

```bash
oak clone https://github.com/acme/web.git
oak clone git@github.com:acme/web.git
oak clone https://git.example.com/acme/web.git my-dir    # choose the directory
```

Oak runs your system `git clone` (so `git` must be on your `PATH`, and your Git credentials apply), creates an Oak repo, replays every commit onto `main`, and leaves you on a personal branch at the tip. It then offers to delete the now-redundant `.git` directory — keeping it if you decline or there's no terminal to ask.

**What counts as a Git URL:** anything starting with `git@`, `ssh://`, or `git://`; anything ending in `.git`; and github.com, gitlab.com, and bitbucket.org URLs. For a self-hosted server over HTTPS, make sure the URL ends in `.git` so Oak doesn't read it as an Oak `org/repo`.

Oak-only flags (`--branch`, `--path`, `--detached`, `--from`, `--json`) are rejected with a Git URL — the importer always brings the checked-out history.

## Convert a checkout in place

```bash
cd my-existing-git-repo
oak init
# Detected an existing git repository here. Import its history into oak?
```

Accept, and Oak replays the Git history onto `main`, puts you on a personal branch at the tip, and offers to remove `.git`. Decline, and your `.git` is untouched — handy if you want to keep using Git alongside for a while. (The prompt needs a terminal.)

## Publish what you imported

A CLI import lives on your machine until you push. The first push names the owner, which creates the repo on oak.space:

```bash
oak push --repo acme/web
```

Then merge your branch, or start working — see the [Quickstart](/docs/quickstart).

## What's preserved

**Kept:**

- The full commit graph in order, including both parents of merge commits.
- Every commit's original author, email, message, and timestamp.
- File modes: regular, executable, and symlinks.

**Dropped or simplified:**

- **Submodules** are skipped — Oak has no submodule concept.
- **Octopus merges** (three or more parents) keep their first two parents.
- **Only one line of history** comes across: the checked-out `HEAD` for CLI imports, or the branch you pick on the web. Other branches and tags aren't recreated.

Your first `oak status` after importing is clean: Oak rewrites the working tree from its own records, so `.gitattributes` smudge filters and leftover submodule directories don't show up as changes. Your `.gitignore` keeps working — Oak reads it when there's no `.oakignore`.

## Upload a folder

When creating a repo on oak.space, you can upload a folder from your computer instead of starting empty. The import dialog has presets for Godot, Unity, and Unreal projects that skip their generated directories. Files can also be uploaded into an existing repo from its page.

## Export back to Git

```bash
oak export ../web-as-git
oak export ../web-as-git --branch main --git-branch main
```

`oak export` replays an Oak branch's history (by default the current one) into a brand-new Git repository, preserving each commit's author, email, and timestamp. Push it anywhere. This is Oak's documented escape hatch: your code and its history are never trapped.

| Flag | Effect |
|---|---|
| `-b, --branch` | The Oak branch to export (default: current). |
| `--git-branch` | Name of the branch in the Git repo (default: same as the Oak branch). |
| `-f, --force` | Write into a destination that isn't empty. |
| `--tree-only --at <commit>` | Write just one commit's files, without history. |

## Clone an Oak repo with Git

```bash
git clone https://oak.space/acme/web.git
```

Every Oak repo can be cloned by stock Git — and anything built on it, like package managers, deploy scripts, or Claude Code's `/plugin marketplace add` — as a **read-only snapshot of `main`**:

- It's a **single commit** containing `main`'s current files, with no history. Use `oak export` for history.
- It's **fetch-only**; `git push` to it fails.
- It works for **public repos**, and for the `@public` paths of a private repo. The endpoint doesn't accept API keys or passwords yet, so a private repo answers "not found" to `git` — use `oak clone` or `oak export` for those.
- [Path permissions](/docs/path-permissions) apply: restricted files are left out, and for outsiders only `@public` paths are included.

## Mirror to GitHub

A repo can keep a copy of `main` on GitHub — as a backup, or to run GitHub Actions or other GitHub-side tooling. Set it up under the repo's **Settings → Export**:

1. Create an **empty** repo on GitHub, and make sure Oak's GitHub App (or your connected GitHub account) can push to it.
2. Choose it, and the branch to mirror to.

On every merge to `main` (and whenever you click **Sync now**), Oak writes `main`'s current files to that GitHub branch as **a single snapshot commit and force-pushes it**. Like the Git clone endpoint, it's the current state, not a history replay. Because it force-pushes, use a repo or branch dedicated to the mirror; Oak refuses to overwrite a branch whose latest commit it didn't create. Files over 100 MB can't be mirrored (GitHub's limit), and restricted paths are left out.
