> ## 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](https://code.storage/docs/repos/forking.md)
when you need separate repository access.

The other namespace, [Import Namespace](https://code.storage/docs/repos/imports.md), 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: `base_branch` in
  [`repos.commits.create`](https://code.storage/docs/api/repos/commit-pack), or `base_ref` in
  [`repos.branches.create`](https://code.storage/docs/api/repos/branch-create). 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. An operation reads an ephemeral ref when you
  set its `ephemeral` field, and writes one when you set `target_is_ephemeral`. `base_is_ephemeral`
  and `source_is_ephemeral` read the base or the source from the ephemeral namespace.

## SDK examples

### Create an ephemeral branch

Set `target_is_ephemeral` to write a commit to the ephemeral namespace. Set `ephemeral` to read or
list the files of an ephemeral branch. In Go, the fields are `TargetIsEphemeral` and `Ephemeral`.

```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
import { Pierre } from '@pierre/sdk';

const pierre = new Pierre(); // reads PIERRE_ORG and PIERRE_PRIVATE_KEY

// Create an ephemeral branch from "main".
const preview = await pierre.repos.commits.create({
  repo_name: 'acme/web',
  target_branch: 'preview/pr-123',
  base_branch: 'main',
  target_is_ephemeral: true, // Write to the ephemeral namespace.
  commit_message: 'Preview environment for PR 123',
  author: { name: 'CI Bot', email: 'ci@example.com' },
  files: [{ path: 'index.html', content: '<h1>Preview</h1>' }],
});
console.log(preview.commit.commit_sha);

// Read a file from the ephemeral branch.
const response = await pierre.repos.files.get({
  repo_name: 'acme/web',
  path: 'index.html',
  ref: 'preview/pr-123',
  ephemeral: true, // Read from the ephemeral namespace.
});
console.log(await response.text());

// List files in the ephemeral branch.
const files = await pierre.repos.files.list({
  repo_name: 'acme/web',
  ref: 'preview/pr-123',
  ephemeral: true,
});
console.log(files.body.paths);
```

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
from pierre import Pierre

pierre = Pierre()  # reads PIERRE_ORG and PIERRE_PRIVATE_KEY

# Create an ephemeral branch from "main".
preview = pierre.repos.commits.create(
    repo_name="acme/web",
    target_branch="preview/pr-123",
    base_branch="main",
    target_is_ephemeral=True,  # Write to the ephemeral namespace.
    commit_message="Preview environment for PR 123",
    author={"name": "CI Bot", "email": "ci@example.com"},
    files=[{"path": "index.html", "content": "<h1>Preview</h1>"}],
)
print(preview["commit"]["commit_sha"])

# Read a file from the ephemeral branch.
response = pierre.repos.files.get(
    repo_name="acme/web",
    path="index.html",
    ref="preview/pr-123",
    ephemeral=True,  # Read from the ephemeral namespace.
)
html = response.read()
response.close()
print(html.decode())

# List files in the ephemeral branch.
files = pierre.repos.files.list(repo_name="acme/web", ref="preview/pr-123", ephemeral=True)
print(files.body["paths"])
```

```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
import (
	"context"
	"fmt"
	"io"
	"strings"

	pierre "github.com/pierrecomputer/sdk/go"
)

ctx := context.Background()
client, err := pierre.NewClient() // reads PIERRE_ORG and PIERRE_PRIVATE_KEY
if err != nil {
	return err
}

// Create an ephemeral branch from "main".
preview, err := client.Repos.Commits.Create(ctx, pierre.ReposCommitsCreateParams{
	RepoName:          "acme/web",
	TargetBranch:      "preview/pr-123",
	BaseBranch:        pierre.String("main"),
	TargetIsEphemeral: pierre.Bool(true), // Write to the ephemeral namespace.
	CommitMessage:     "Preview environment for PR 123",
	Author:            pierre.GitIdentity{Name: "CI Bot", Email: "ci@example.com"},
	Files: []pierre.CommitFile{
		{Path: "index.html", Content: strings.NewReader("<h1>Preview</h1>")},
	},
})
if err != nil {
	return err
}
fmt.Println(preview.Commit.CommitSHA)

// Read a file from the ephemeral branch.
file, err := client.Repos.Files.Get(ctx, pierre.ReposFilesGetParams{
	RepoName:  "acme/web",
	Path:      "index.html",
	Ref:       pierre.String("preview/pr-123"),
	Ephemeral: pierre.Bool(true), // Read from the ephemeral namespace.
})
if err != nil {
	return err
}
defer file.Close()
html, err := io.ReadAll(file)
if err != nil {
	return err
}
fmt.Println(string(html))

// List files in the ephemeral branch.
files, err := client.Repos.Files.List(ctx, pierre.ReposFilesListParams{
	RepoName:  "acme/web",
	Ref:       pierre.String("preview/pr-123"),
	Ephemeral: pierre.Bool(true),
})
if err != nil {
	return err
}
fmt.Println(files.Body.Paths)
```

### Branch from an ephemeral base

Set `base_is_ephemeral` when another ephemeral branch is the base. Also set `base_branch`.

```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
const variant = await pierre.repos.commits.create({
  repo_name: 'acme/web',
  target_branch: 'preview/pr-123-variant',
  base_branch: 'preview/pr-123',
  base_is_ephemeral: true, // Use another ephemeral branch as the base.
  target_is_ephemeral: true,
  commit_message: 'Variant of preview environment',
  author: { name: 'CI Bot', email: 'ci@example.com' },
  files: [{ path: 'variant.txt', content: 'This is a variant\n' }],
});
console.log(variant.commit.commit_sha);
```

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
variant = pierre.repos.commits.create(
    repo_name="acme/web",
    target_branch="preview/pr-123-variant",
    base_branch="preview/pr-123",
    base_is_ephemeral=True,  # Use another ephemeral branch as the base.
    target_is_ephemeral=True,
    commit_message="Variant of preview environment",
    author={"name": "CI Bot", "email": "ci@example.com"},
    files=[{"path": "variant.txt", "content": "This is a variant\n"}],
)
print(variant["commit"]["commit_sha"])
```

```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
variant, err := client.Repos.Commits.Create(ctx, pierre.ReposCommitsCreateParams{
	RepoName:          "acme/web",
	TargetBranch:      "preview/pr-123-variant",
	BaseBranch:        pierre.String("preview/pr-123"),
	BaseIsEphemeral:   pierre.Bool(true), // Use another ephemeral branch as the base.
	TargetIsEphemeral: pierre.Bool(true),
	CommitMessage:     "Variant of preview environment",
	Author:            pierre.GitIdentity{Name: "CI Bot", Email: "ci@example.com"},
	Files: []pierre.CommitFile{
		{Path: "variant.txt", Content: strings.NewReader("This is a variant\n")},
	},
})
if err != nil {
	return err
}
fmt.Println(variant.Commit.CommitSHA)
```

### Promote an ephemeral branch

Promote an ephemeral branch to the default namespace with
[`repos.branches.create`](https://code.storage/docs/api/repos/branch-create). Keep the same branch name or use a new name.

```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
// Keep the same branch name.
await pierre.repos.branches.create({
  repo_name: 'acme/web',
  base_ref: 'preview/pr-123',
  base_is_ephemeral: true,
  target_branch: 'preview/pr-123',
});

// Use a new target name.
const promoted = await pierre.repos.branches.create({
  repo_name: 'acme/web',
  base_ref: 'preview/pr-123',
  base_is_ephemeral: true,
  target_branch: 'feature/awesome-change',
});
console.log(promoted.target_branch); // 'feature/awesome-change'
```

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
# Keep the same branch name.
pierre.repos.branches.create(
    repo_name="acme/web",
    base_ref="preview/pr-123",
    base_is_ephemeral=True,
    target_branch="preview/pr-123",
)

# Use a new target name.
promoted = pierre.repos.branches.create(
    repo_name="acme/web",
    base_ref="preview/pr-123",
    base_is_ephemeral=True,
    target_branch="feature/awesome-change",
)
print(promoted["target_branch"])  # "feature/awesome-change"
```

```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
// Keep the same branch name.
same, err := client.Repos.Branches.Create(ctx, pierre.ReposBranchesCreateParams{
	RepoName:        "acme/web",
	BaseRef:         pierre.String("preview/pr-123"),
	BaseIsEphemeral: pierre.Bool(true),
	TargetBranch:    pierre.String("preview/pr-123"),
})
if err != nil {
	return err
}
fmt.Println(same.TargetBranch)

// Use a new target name.
promoted, err := client.Repos.Branches.Create(ctx, pierre.ReposBranchesCreateParams{
	RepoName:        "acme/web",
	BaseRef:         pierre.String("preview/pr-123"),
	BaseIsEphemeral: pierre.Bool(true),
	TargetBranch:    pierre.String("feature/awesome-change"),
})
if err != nil {
	return err
}
fmt.Println(promoted.TargetBranch) // feature/awesome-change
```

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


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