Skip to main content
Forking creates a new repository from an existing Code Storage repository at a specific point in time. Unlike GitHub sync (which maintains a live connection), forks are independent copies—changes to the original don’t affect the fork, and vice versa.

When to use forking

  • Templates: Create new projects from a starter template
  • Experimentation: Test changes without affecting the original repository
  • Snapshots: Capture a repository’s state at a specific commit or branch
  • Isolation: Give each user or agent their own copy to work with

Quick start

import { GitStorage } from '@pierre/storage';

const store = new GitStorage({
  name: 'your-org',
  key: process.env.PIERRE_PRIVATE_KEY,
});

// Fork at the latest commit (HEAD)
const fork = await store.createRepo({
  id: 'my-fork',
  baseRepo: {
    id: 'template-repo',  // Source repository ID
  },
});

// Fork at a specific branch
const branchFork = await store.createRepo({
  id: 'feature-fork',
  baseRepo: {
    id: 'template-repo',
    ref: 'develop',  // Fork from tip of 'develop' branch
  },
});

// Fork at a specific commit
const commitFork = await store.createRepo({
  id: 'snapshot-fork',
  baseRepo: {
    id: 'template-repo',
    sha: 'abc123def456...',  // Fork at exact commit
  },
});

Fork options

ParameterTypeDescription
idRequiredThe repository ID (name) to fork from
refOptionalBranch or tag name to fork from. Forks the tip of this ref.
shaOptionalExact commit SHA to fork at. Overrides ref if both are provided.
Resolution order:
  1. If sha is provided, fork at that exact commit
  2. If ref is provided, fork at the tip of that branch/tag
  3. Otherwise, fork at the source repository’s HEAD

Default branch behavior

The forked repository inherits the default branch from the source:
// Source repo has 'main' as default branch
const fork = await store.createRepo({
  baseRepo: { id: 'source-repo' },
});
console.log(fork.defaultBranch); // 'main' (inherited)

// Override the default branch
const customFork = await store.createRepo({
  baseRepo: { id: 'source-repo' },
  defaultBranch: 'develop',
});
console.log(customFork.defaultBranch); // 'develop'

Use cases

Project templates

Create new projects from a starter template:
async function createProjectFromTemplate(
  templateId: string,
  projectName: string,
  userId: string
) {
  const project = await store.createRepo({
    id: `${userId}/${projectName}`,
    baseRepo: { id: templateId },
  });

  // Customize the new project
  await project.createCommit({
    targetBranch: 'main',
    commitMessage: 'Initialize project',
    author: { name: 'System', email: 'system@example.com' },
  })
    .addFileFromString('README.md', `# ${projectName}\n\nCreated by ${userId}`)
    .send();

  return project;
}

// Usage
const project = await createProjectFromTemplate(
  'templates/react-starter',
  'my-new-app',
  'user-123'
);

Per-agent workspaces

Give each AI agent its own isolated copy:
async function createAgentWorkspace(
  sourceRepo: string,
  agentId: string,
  taskId: string
) {
  // Fork the source repo for this agent's task
  const workspace = await store.createRepo({
    id: `agents/${agentId}/${taskId}`,
    baseRepo: { id: sourceRepo },
  });

  // Agent can now work independently
  const url = await workspace.getRemoteURL({
    permissions: ['git:read', 'git:write'],
    ttl: 3600,
  });

  return { workspace, url };
}

Point-in-time snapshots

Capture a repository’s state before making risky changes:
async function createSnapshot(repoId: string, label: string) {
  const source = await store.findOne({ id: repoId });
  const commits = await source.listCommits({ limit: 1 });
  const headSha = commits.commits[0].sha;

  const snapshot = await store.createRepo({
    id: `snapshots/${repoId}/${label}`,
    baseRepo: {
      id: repoId,
      sha: headSha,
    },
  });

  return snapshot;
}

// Before a major refactor
const backup = await createSnapshot('my-project', 'pre-refactor-2024-01');

Forking vs GitHub sync

FeatureForkingGitHub Sync
SourceCode Storage repositoriesGitHub repositories
ConnectionOne-time copyContinuous sync
UpdatesIndependent after forkAutomatically synced
Use caseTemplates, snapshots, isolationMirror GitHub repos
Use forking when you want an independent copy. Use GitHub sync when you want to maintain a live connection to a GitHub repository.

Limitations

  • Same organization: You can only fork repositories within your own organization
  • No relationship tracking: Forks are independent—there’s no “parent” reference after creation
  • Full copy: Forks include all branches and history up to the fork point