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

# Git 集成

PPIO Sandbox 提供 `sandbox.git` 辅助方法,覆盖克隆、分支管理、提交、拉取、推送、管理远程仓库和配置 Git 等常见仓库工作流。

## 认证与身份

### 内联凭证

对于私有 HTTPS 仓库,可将用户名和密码或 token 直接传给 `push`、`pull`、`clone` 等操作。

<CodeGroup>
  ```python Python theme={null}
  from ppio_sandbox import PPIO
  import os

  ppio = PPIO()

  sandbox = ppio.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'),
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO()

  const sandbox = await ppio.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,
  })
  ```
</CodeGroup>

### 使用 Git 凭证助手一次性认证

你可以在 JavaScript 中使用 `dangerouslyAuthenticate()`,或在 Python 中使用 `dangerously_authenticate()`,将凭证存储到 Sandbox 的凭证助手中。

<Warning>
  凭证会写入 Sandbox 内的磁盘,任何拥有 Sandbox 访问权限的对象都可以读取。
</Warning>

凭证默认可为 GitHub 存储,也可为自定义 HTTPS 主机存储。

<CodeGroup>
  ```python Python theme={null}
  from ppio_sandbox import PPIO
  import os

  ppio = PPIO()

  sandbox = ppio.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')
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO()

  const sandbox = await ppio.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')
  ```
</CodeGroup>

### 在远程 URL 中保留凭证

默认情况下,克隆完成后凭证会从远程 URL 中移除。若要将其保留在 `.git/config` 中,请设置 `dangerouslyStoreCredentials: true`(JS)或 `dangerously_store_credentials=True`(Python)。

<Warning>
  保留在远程 URL 中的凭证会留在仓库配置里,并可被 Sandbox 内的进程读取。
</Warning>

<CodeGroup>
  ```python Python theme={null}
  from ppio_sandbox import PPIO
  import os

  ppio = PPIO()

  sandbox = ppio.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,
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO()

  const sandbox = await ppio.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,
  })
  ```
</CodeGroup>

## 配置提交身份

你可以使用 `configureUser`(JS)或 `configure_user`(Python)在全局或仓库本地范围设置提交作者信息。

<CodeGroup>
  ```python Python theme={null}
  from ppio_sandbox import PPIO

  ppio = PPIO()

  sandbox = ppio.sandbox.create()

  sandbox.git.configure_user('PPIO Bot', 'bot@example.com')

  sandbox.git.configure_user(
      'PPIO Bot',
      'bot@example.com',
      scope='local',
      path=repo_path,
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO()

  const sandbox = await ppio.sandbox.create()

  await sandbox.git.configureUser('PPIO Bot', 'bot@example.com')

  await sandbox.git.configureUser('PPIO Bot', 'bot@example.com', {
    scope: 'local',
    path: repoPath,
  })
  ```
</CodeGroup>

## 克隆仓库

支持的克隆选项包括目标路径、分支选择、克隆深度、用户名、密码以及凭证存储行为。

<CodeGroup>
  ```python Python theme={null}
  from ppio_sandbox import PPIO

  ppio = PPIO()

  sandbox = ppio.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)
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO()

  const sandbox = await ppio.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,
  })
  ```
</CodeGroup>

## 查看仓库状态与分支

你可以使用 `status()` 查看当前分支、领先/落后提交数以及文件状态。

你可以使用 `branches()` 获取分支列表和当前分支。

<CodeGroup>
  ```python Python theme={null}
  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)
  ```

  ```typescript JavaScript & TypeScript theme={null}
  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)
  ```
</CodeGroup>

## 创建、切换与删除分支

<CodeGroup>
  ```python Python theme={null}
  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,
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  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,
  })
  ```
</CodeGroup>

## 暂存与提交变更

你可以使用 `add` 暂存全部变更或指定文件。

你可以使用 `commit` 创建提交,选项包括自定义作者名称、作者邮箱以及空提交。

<CodeGroup>
  ```python Python theme={null}
  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='PPIO Bot',
      author_email='bot@example.com',
      allow_empty=True,
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  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: 'PPIO Bot',
    authorEmail: 'bot@example.com',
    allowEmpty: true,
  })
  ```
</CodeGroup>

## 拉取与推送

`push` 和 `pull` 默认可使用已配置的 upstream。你也可以指定 remote、分支和 upstream 配置。

<CodeGroup>
  ```python Python theme={null}
  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',
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  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',
  })
  ```
</CodeGroup>

## 管理远程仓库

你可以使用 `remoteAdd`(JS)或 `remote_add`(Python)添加远程仓库,可选择添加后立即抓取,或覆盖已有的远程仓库。

<CodeGroup>
  ```python Python theme={null}
  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,
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  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,
  })
  ```
</CodeGroup>

## Git 配置

你可以使用 `setConfig` / `set_config` 和 `getConfig` / `get_config` 在全局或仓库级别管理 Git 设置。

<CodeGroup>
  ```python Python theme={null}
  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,
  )
  ```

  ```typescript JavaScript & TypeScript theme={null}
  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,
  })
  ```
</CodeGroup>
