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

# Git Integration

Novita Sandbox exposes `sandbox.git` helpers for common repository workflows such as cloning, branching, committing, pulling, pushing, managing remotes, and configuring Git.

## Authentication and identity

### Inline credentials

For private HTTPS repositories, pass both a username and password/token directly into operations such as `push`, `pull`, or `clone`.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  import { Sandbox } from 'novita-sandbox'

  const sandbox = await Sandbox.create()

  await sandbox.git.push(repoPath, {
    username: process.env.GIT_USERNAME,
    password: process.env.GIT_TOKEN,
  })

  await sandbox.git.pull(repoPath, {
    username: process.env.GIT_USERNAME,
    password: process.env.GIT_TOKEN,
  })
  ```

  ```python Python icon="python" theme={"system"}
  from novita_sandbox.core import Sandbox
  import os

  sandbox = Sandbox.create()

  sandbox.git.push(
      repo_path,
      username=os.environ.get("GIT_USERNAME"),
      password=os.environ.get("GIT_TOKEN"),
  )

  sandbox.git.pull(
      repo_path,
      username=os.environ.get("GIT_USERNAME"),
      password=os.environ.get("GIT_TOKEN"),
  )
  ```
</CodeGroup>

### Authenticate once with the Git credential helper

You can use `dangerouslyAuthenticate()` in JavaScript or `dangerously_authenticate()` in Python to store credentials inside the sandbox credential helper.

<Warning>
  Credentials are written to disk inside the sandbox and can be read by anything with sandbox access.
</Warning>

Credentials may be stored for GitHub by default or for a custom HTTPS host.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.dangerouslyAuthenticate({
    username: process.env.GIT_USERNAME,
    password: process.env.GIT_TOKEN,
  })

  await sandbox.git.dangerouslyAuthenticate({
    username: process.env.GIT_USERNAME,
    password: process.env.GIT_TOKEN,
    host: 'git.example.com',
    protocol: 'https',
  })

  await sandbox.git.clone('https://git.example.com/org/repo.git', {
    path: '/home/user/repo',
  })

  await sandbox.git.push('/home/user/repo')
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.dangerously_authenticate(
      username=os.environ.get("GIT_USERNAME"),
      password=os.environ.get("GIT_TOKEN"),
  )

  sandbox.git.dangerously_authenticate(
      username=os.environ.get("GIT_USERNAME"),
      password=os.environ.get("GIT_TOKEN"),
      host="git.example.com",
      protocol="https",
  )

  sandbox.git.clone(
      "https://git.example.com/org/repo.git",
      path="/home/user/repo",
  )

  sandbox.git.push("/home/user/repo")
  ```
</CodeGroup>

### Keep credentials in the remote URL

By default, credentials are removed from the remote URL after clone. To retain them in `.git/config`, set `dangerouslyStoreCredentials: true` (JS) or `dangerously_store_credentials=True` (Python).

<Warning>
  Credentials kept in a remote URL remain in repo config and are readable by sandbox processes.
</Warning>

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.clone('https://git.example.com/org/repo.git', {
    path: '/home/user/repo',
    username: process.env.GIT_USERNAME,
    password: process.env.GIT_TOKEN,
  })

  await sandbox.git.clone('https://git.example.com/org/repo.git', {
    path: '/home/user/repo',
    username: process.env.GIT_USERNAME,
    password: process.env.GIT_TOKEN,
    dangerouslyStoreCredentials: true,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.clone(
      "https://git.example.com/org/repo.git",
      path="/home/user/repo",
      username=os.environ.get("GIT_USERNAME"),
      password=os.environ.get("GIT_TOKEN"),
  )

  sandbox.git.clone(
      "https://git.example.com/org/repo.git",
      path="/home/user/repo",
      username=os.environ.get("GIT_USERNAME"),
      password=os.environ.get("GIT_TOKEN"),
      dangerously_store_credentials=True,
  )
  ```
</CodeGroup>

## Configure commit identity

You can use `configureUser` (JS) or `configure_user` (Python) to set commit author details globally or locally for a repository.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.configureUser('Novita Bot', 'bot@example.com')

  await sandbox.git.configureUser('Novita Bot', 'bot@example.com', {
    scope: 'local',
    path: repoPath,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.configure_user("Novita Bot", "bot@example.com")

  sandbox.git.configure_user(
      "Novita Bot",
      "bot@example.com",
      scope="local",
      path=repo_path,
  )
  ```
</CodeGroup>

## Clone repositories

Supported clone options include destination path, branch selection, depth, username, password, and credential-storage behavior.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.clone(repoUrl, {
    path: repoPath,
  })

  await sandbox.git.clone(repoUrl, {
    path: repoPath,
    branch: 'main',
  })

  await sandbox.git.clone(repoUrl, {
    path: repoPath,
    depth: 1,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.clone(repo_url, path=repo_path)

  sandbox.git.clone(repo_url, path=repo_path, branch="main")

  sandbox.git.clone(repo_url, path=repo_path, depth=1)
  ```
</CodeGroup>

## Check repository status and branches

You can use `status()` to inspect current branch, ahead/behind counts, and file status.

You can use `branches()` to get the branch list and current branch.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  const status = await sandbox.git.status(repoPath)
  console.log(status.currentBranch)
  console.log(status.ahead)
  console.log(status.behind)
  console.log(status.fileStatus)

  const branches = await sandbox.git.branches(repoPath)
  console.log(branches.currentBranch)
  console.log(branches.branches)
  ```

  ```python Python icon="python" theme={"system"}
  status = sandbox.git.status(repo_path)
  print(status.current_branch)
  print(status.ahead)
  print(status.behind)
  print(status.file_status)

  branches = sandbox.git.branches(repo_path)
  print(branches.current_branch)
  print(branches.branches)
  ```
</CodeGroup>

## Create, switch, and delete branches

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.createBranch(repoPath, 'feature/new-docs')

  await sandbox.git.checkoutBranch(repoPath, 'main')

  await sandbox.git.deleteBranch(repoPath, 'feature/old-docs')

  await sandbox.git.deleteBranch(repoPath, 'feature/stale-docs', {
    force: true,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.create_branch(repo_path, "feature/new-docs")

  sandbox.git.checkout_branch(repo_path, "main")

  sandbox.git.delete_branch(repo_path, "feature/old-docs")

  sandbox.git.delete_branch(
      repo_path,
      "feature/stale-docs",
      force=True,
  )
  ```
</CodeGroup>

## Stage and commit changes

You can use `add` to stage all changes or selected files.

You can use `commit` to create commits. Options include custom author name, author email, and empty commits.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.add(repoPath)

  await sandbox.git.commit(repoPath, 'Initial commit')

  await sandbox.git.add(repoPath, {
    files: ['README.md', 'src/index.ts'],
  })

  await sandbox.git.commit(repoPath, 'Docs sync', {
    authorName: 'Novita Bot',
    authorEmail: 'bot@example.com',
    allowEmpty: true,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.add(repo_path)

  sandbox.git.commit(repo_path, "Initial commit")

  sandbox.git.add(
      repo_path,
      files=["README.md", "src/index.ts"],
  )

  sandbox.git.commit(
      repo_path,
      "Docs sync",
      author_name="Novita Bot",
      author_email="bot@example.com",
      allow_empty=True,
  )
  ```
</CodeGroup>

## Pull and push

`push` and `pull` can use the configured upstream by default. You can also specify remote, branch, and upstream configuration.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.push(repoPath)

  await sandbox.git.pull(repoPath)

  await sandbox.git.push(repoPath, {
    remote: 'origin',
    branch: 'main',
    setUpstream: true,
  })

  await sandbox.git.pull(repoPath, {
    remote: 'origin',
    branch: 'main',
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.push(repo_path)

  sandbox.git.pull(repo_path)

  sandbox.git.push(
      repo_path,
      remote="origin",
      branch="main",
      set_upstream=True,
  )

  sandbox.git.pull(
      repo_path,
      remote="origin",
      branch="main",
  )
  ```
</CodeGroup>

## Manage remotes

You can use `remoteAdd` (JS) or `remote_add` (Python) to add remotes, optionally fetch after adding, or overwrite an existing remote.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.remoteAdd(repoPath, 'origin', repoUrl)

  await sandbox.git.remoteAdd(repoPath, 'origin', repoUrl, {
    fetch: true,
  })

  await sandbox.git.remoteAdd(repoPath, 'origin', repoUrl, {
    overwrite: true,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.remote_add(repo_path, "origin", repo_url)

  sandbox.git.remote_add(
      repo_path,
      "origin",
      repo_url,
      fetch=True,
  )

  sandbox.git.remote_add(
      repo_path,
      "origin",
      repo_url,
      overwrite=True,
  )
  ```
</CodeGroup>

## Git configuration

You can use `setConfig` / `set_config` and `getConfig` / `get_config` to manage Git settings globally or per repository.

<CodeGroup>
  ```js JavaScript & TypeScript icon="js" theme={"system"}
  await sandbox.git.setConfig('pull.rebase', 'false')

  const value = await sandbox.git.getConfig('pull.rebase')

  await sandbox.git.setConfig('pull.rebase', 'false', {
    scope: 'local',
    path: repoPath,
  })

  const localValue = await sandbox.git.getConfig('pull.rebase', {
    scope: 'local',
    path: repoPath,
  })
  ```

  ```python Python icon="python" theme={"system"}
  sandbox.git.set_config("pull.rebase", "false")

  value = sandbox.git.get_config("pull.rebase")

  sandbox.git.set_config(
      "pull.rebase",
      "false",
      scope="local",
      path=repo_path,
  )

  local_value = sandbox.git.get_config(
      "pull.rebase",
      scope="local",
      path=repo_path,
  )
  ```
</CodeGroup>
