> ## Documentation Index
> Fetch the complete documentation index at: https://docs.novita.ai/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 a username and password or token directly to operations such as `push`, `pull`, or `clone`.

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

  const novita = new Novita()
  const sandbox = await novita.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 import Novita
  import os

  novita = Novita()
  sandbox = novita.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.

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

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

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

  const novita = new Novita()
  const sandbox = await novita.sandbox.create()

  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"}
  from novita_sandbox import Novita
  import os

  novita = Novita()
  sandbox = novita.sandbox.create()

  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).

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

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

  const novita = new Novita()
  const sandbox = await novita.sandbox.create()

  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"}
  from novita_sandbox import Novita
  import os

  novita = Novita()
  sandbox = novita.sandbox.create()

  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"}
  import { Novita } from 'novita-sandbox'

  const novita = new Novita()
  const sandbox = await novita.sandbox.create()

  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"}
  from novita_sandbox import Novita

  novita = Novita()
  sandbox = novita.sandbox.create()

  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"}
  import { Novita } from 'novita-sandbox'

  const novita = new Novita()
  const sandbox = await novita.sandbox.create()

  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"}
  from novita_sandbox import Novita

  novita = Novita()
  sandbox = novita.sandbox.create()

  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>
