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

# Ephemeral Namespace

> Create isolated refs for previews, CI artifacts, and experiments. Promote an ephemeral branch to the default namespace.

The `+ephemeral` namespace stores refs separately from the default namespace. Use it for previews,
CI artifacts, and other isolated work.

Insert `+ephemeral` before `.git` in the repository URL:

```bash theme={"theme":{"light":"github-light","dark":"min-dark"}}
git push https://t:JWT@your-org.code.storage/repo-id+ephemeral.git HEAD:preview/pr-123
```

Two rules apply to every ref that you write through this URL:

* **A normal `git clone` does not show the ref.** Code Storage puts the ref in the ephemeral
  namespace. The normal repository URL hides that namespace.
* **A connected GitHub repository does not receive the ref.** Code Storage never mirrors an
  ephemeral ref to an upstream host.

An ephemeral branch gives you isolation inside one repository. It shares the Git objects and access
rules. It remains until you delete or promote it.

Promote an ephemeral branch when you want it in the default namespace. Use a [fork](/docs/guides/forking)
when you need separate repository access.

The other namespace, [Import Namespace](/docs/guides/imports), accepts a push only and follows different
rules.

## Setup

Add a named remote when you use the namespace often:

```bash theme={"theme":{"light":"github-light","dark":"min-dark"}}
git remote add ephemeral https://t:JWT@your-org.code.storage/repo-id+ephemeral.git
```

This remote accepts standard Git commands.

## Quick start

Push and pull ephemeral branches with standard Git commands:

```bash theme={"theme":{"light":"github-light","dark":"min-dark"}}
git push ephemeral feature-branch
git pull ephemeral feature-branch
```

## Promote a branch

Fetch an ephemeral branch. Then push it to the main remote.

```bash theme={"theme":{"light":"github-light","dark":"min-dark"}}
git fetch ephemeral feature:feature
git push origin feature
```

## Behavior

* **Base**: Name a base for each ephemeral branch. Use `baseBranch` / `baseRef` in the API. When you
  work with Git, clone the normal remote as your base. The ephemeral remote has no default branch.
* **Isolation**: An ephemeral branch can have the same name as a branch in the default namespace.
  The two branches remain separate until promotion.
* **Shared objects**: Ephemeral branches reuse Git objects that are already in the repository. This
  reduces storage use.
* **HTTP API and Git**: Git operations work as usual. HTTP API methods can read and write ephemeral
  refs when they accept `ephemeral` or `ephemeral_base`.

## SDK examples

### Create an ephemeral branch

In the Python SDK, set `ephemeral=True` in calls that create commits, read files, or list files. In
TypeScript, set `ephemeral: true`.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Create an ephemeral branch from "main".
  const preview = await repo
    .createCommit({
      targetBranch: 'preview/pr-123',
      baseBranch: 'main',
      ephemeral: true, // Use the ephemeral namespace.
      commitMessage: 'Preview environment for PR 123',
      author: { name: 'CI Bot', email: 'ci@example.com' },
    })
    .addFileFromString('index.html', '<h1>Preview</h1>')
    .send();

  // Read a file from the ephemeral branch.
  const response = await repo.getFileStream({
    path: 'index.html',
    ref: 'preview/pr-123',
    ephemeral: true, // Read from the ephemeral namespace.
  });
  const html = await response.text();
  console.log(html);

  // List files in the ephemeral branch.
  const files = await repo.listFiles({
    ref: 'preview/pr-123',
    ephemeral: true,
  });
  console.log(files.paths);
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  # Create an ephemeral branch from 'main'.
  result = await (
      repo.create_commit(
          target_branch="preview/pr-123",
          base_branch="main",
          ephemeral=True,  # Use the ephemeral namespace.
          commit_message="Preview environment for PR 123",
          author={"name": "CI Bot", "email": "ci@example.com"},
      )
      .add_file_from_string("index.html", "<h1>Preview</h1>")
      .send()
  )

  # Read a file from the ephemeral branch.
  response = await repo.get_file_stream(
      path="index.html",
      ref="preview/pr-123",
      ephemeral=True,  # Read from the ephemeral namespace.
  )
  content = await response.aread()

  # List files in the ephemeral branch.
  files = await repo.list_files(
      ref="preview/pr-123",
      ephemeral=True,
  )
  print(files["paths"])
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Create an ephemeral branch from "main".
  builder, err := repo.CreateCommit(storage.CommitOptions{
  	TargetBranch:  "preview/pr-123",
  	BaseBranch:    "main",
  	Ephemeral:     true,
  	CommitMessage: "Preview environment for PR 123",
  	Author:        storage.CommitSignature{Name: "CI Bot", Email: "ci@example.com"},
  })
  _, err = builder.AddFileFromString("index.html", "<h1>Preview</h1>", nil).Send(context.Background())

  // Read a file from the ephemeral branch.
  ephemeral := true
  resp, err := repo.FileStream(context.Background(), storage.GetFileOptions{
  	Path:      "index.html",
  	Ref:       "preview/pr-123",
  	Ephemeral: &ephemeral,
  })
  defer resp.Body.Close()

  // List files in the ephemeral branch.
  files, err := repo.ListFiles(context.Background(), storage.ListFilesOptions{
  	Ref:       "preview/pr-123",
  	Ephemeral: &ephemeral,
  })
  fmt.Println(files.Paths)
  ```
</CodeGroup>

### Branch from an ephemeral base

Mark the base as ephemeral when another ephemeral branch is the base. You must also set the base
branch.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  const variant = await repo
    .createCommit({
      targetBranch: 'preview/pr-123-variant',
      baseBranch: 'preview/pr-123',
      ephemeral: true,
      ephemeralBase: true, // Use another ephemeral branch as the base.
      commitMessage: 'Variant of preview environment',
      author: { name: 'CI Bot', email: 'ci@example.com' },
    })
    .addFileFromString('variant.txt', 'This is a variant\n')
    .send();
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  # Use another ephemeral branch as the base.
  result = await (
      repo.create_commit(
          target_branch="preview/pr-123-variant",
          base_branch="preview/pr-123",
          ephemeral=True,
          ephemeral_base=True,  # Use an ephemeral base.
          commit_message="Variant of preview environment",
          author={"name": "CI Bot", "email": "ci@example.com"},
      )
      .add_file_from_string("variant.txt", "This is a variant\n")
      .send()
  )
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Use another ephemeral branch as the base.
  builder, err := repo.CreateCommit(storage.CommitOptions{
  	TargetBranch:  "preview/pr-123-variant",
  	BaseBranch:    "preview/pr-123",
  	Ephemeral:     true,
  	EphemeralBase: true,
  	CommitMessage: "Variant of preview environment",
  	Author:        storage.CommitSignature{Name: "CI Bot", Email: "ci@example.com"},
  })
  _, err = builder.AddFileFromString("variant.txt", "This is a variant\n", nil).
  	Send(context.Background())
  ```
</CodeGroup>

### Promote an ephemeral branch

Promote an ephemeral branch to the default namespace. Keep the same branch name or use a new name.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Keep the same branch name.
  await repo.createBranch({
    baseRef: 'preview/pr-123',
    baseIsEphemeral: true,
    targetBranch: 'preview/pr-123',
  });

  // Use a new target name.
  const result = await repo.createBranch({
    baseRef: 'preview/pr-123',
    baseIsEphemeral: true,
    targetBranch: 'feature/awesome-change',
  });
  console.log(result.targetBranch); // 'feature/awesome-change'
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  # Keep the same branch name.
  result = await repo.create_branch(
      base_ref="preview/pr-123",
      base_is_ephemeral=True,
      target_branch="preview/pr-123",
  )

  # Use a new target name.
  result = await repo.create_branch(
      base_ref="preview/pr-123",
      base_is_ephemeral=True,
      target_branch="feature/awesome-change",
  )
  print(result["target_branch"])  # "feature/awesome-change"
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // Keep the same branch name.
  result, err := repo.CreateBranch(context.Background(), storage.CreateBranchOptions{
  	BaseRef:         "preview/pr-123",
  	BaseIsEphemeral: true,
  	TargetBranch:    "preview/pr-123",
  })
  fmt.Println(result.TargetBranch)

  // Use a new target name.
  renamed, err := repo.CreateBranch(context.Background(), storage.CreateBranchOptions{
  	BaseRef:         "preview/pr-123",
  	BaseIsEphemeral: true,
  	TargetBranch:    "feature/awesome-change",
  })
  fmt.Println(renamed.TargetBranch)
  ```
</CodeGroup>

This operation keeps the ephemeral branch. Delete that branch when you no longer need it.
