# Git integration
<subtitle>Clone repositories, manage branches, submit and push code within the sandbox. </subtitle>

You can use the `sandbox.git` method to perform common Git operations within the sandbox, including cloning repositories, configuring identities, viewing status, managing branches, committing, pulling, pushing, and managing remote repositories.

## Authentication and identity configuration

### Pass credentials in the command

If you need to access a private warehouse through HTTP(S), you can directly pass in `username` and `password` in the operation that requires authentication. Here `password` is usually the access token. Whenever `password` is passed in, `username` must also be passed in.

```python
import os
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

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"),
)
```

### Using Credential Assistant

If you don't want to pass in credentials for every operation, you can use `dangerously_authenticate()` to write the credentials to the Git credential helper inside the sandbox.

> Credentials will be stored in the sandbox disk. These credentials may be read by any process or agent with access to the sandbox. Please use only after understanding the risks.

```python
import os
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()

#Default for GitHub
sandbox.git.dangerously_authenticate(
    username=os.environ.get("GIT_USERNAME"),
    password=os.environ.get("GIT_TOKEN"),
)

#Self-hosted Git service
sandbox.git.dangerously_authenticate(
    username=os.environ.get("GIT_USERNAME"),
    password=os.environ.get("GIT_TOKEN"),
    host="git.example.com",
    protocol="https",
)

# Subsequent HTTPS Git operations will use the saved credentials
sandbox.git.clone("https://git.example.com/org/repo.git", path="/home/user/repo")
sandbox.git.push("/home/user/repo")
```

### Keep credentials in remote URL

By default, credentials are removed from the remote URL after cloning is complete. If you really need to keep the credentials in the remote URL, i.e. `.git/config` written to the repository, you can set `dangerously_store_credentials=True`.

> Keeping the credentials in the remote URL will make them persist in the repository configuration. These credentials may be read by any process or agent with access to the sandbox or repository directory. Use only when absolutely necessary.

```python
import os
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()

#Default behavior: remove credentials from remote URL after cloning
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"),
)

# Keep credentials in the remote URL
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,
)
```

### Configure submission identity

Before submitting, you usually need to set the name and email address of the Git author. You can configure it as a global identity or only configure a local identity for a certain warehouse.

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

# Global configuration
sandbox.git.configure_user("UCloud Bot", "bot@example.com")

# Warehouse local configuration
sandbox.git.configure_user(
    "UCloud Bot",
    "bot@example.com",
    scope="local",
    path=repo_path,
)
```

## Clone repository

For the authentication method of private warehouse, please refer to [Authentication and Identity Configuration](#Authentication and Identity Configuration).

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_url = "https://git.example.com/org/repo.git"
repo_path = "/home/user/repo"

#Default clone
sandbox.git.clone(repo_url, path=repo_path)

# Clone the specified branch
sandbox.git.clone(repo_url, path=repo_path, branch="main")

# Shallow clone
sandbox.git.clone(repo_url, path=repo_path, depth=1)
```

## View status and branches

`status()` returns a structured object containing the current branch, ahead/behind count, and file status. `branches()` returns the branch list and the current branch.

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

status = sandbox.git.status(repo_path)
print(status.current_branch, status.ahead, status.behind)
print(status.file_status)

branches = sandbox.git.branches(repo_path)
print(branches.current_branch)
print(branches.branches)
```

## Create and manage branches

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

# Create and switch to new branch
sandbox.git.create_branch(repo_path, "feature/new-docs")

# Switch to an existing branch
sandbox.git.checkout_branch(repo_path, "main")

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

#Force deletion of branches
sandbox.git.delete_branch(repo_path, "feature/stale-docs", force=True)
```

## Temporary storage and submission

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

# By default, all changes are staged and submitted using the warehouse configuration.
sandbox.git.add(repo_path)
sandbox.git.commit(repo_path, "Initial commit")

# Temporarily save the specified file
sandbox.git.add(repo_path, files=["README.md", "src/index.py"])

# Allow empty commits and override commit authors
sandbox.git.commit(
    repo_path,
    "Docs sync",
    author_name="UCloud Bot",
    author_email="bot@example.com",
    allow_empty=True,
)
```

## Pull and push

For the authentication method of private warehouse, please refer to [Authentication and Identity Configuration](#Authentication and Identity Configuration).

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

# Default behavior: use upstream if upstream is set
sandbox.git.push(repo_path)
sandbox.git.pull(repo_path)

# Specify remote/branch and set upstream
sandbox.git.push(
    repo_path,
    remote="origin",
    branch="main",
    set_upstream=True,
)

sandbox.git.pull(
    repo_path,
    remote="origin",
    branch="main",
)
```

## Manage remote warehouse

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"
repo_url = "https://git.example.com/org/repo.git"

#Add remote warehouse
sandbox.git.remote_add(repo_path, "origin", repo_url)

# Execute fetch after adding the remote warehouse
sandbox.git.remote_add(repo_path, "origin", repo_url, fetch=True)

# If the remote repository already exists, overwrite the remote URL
sandbox.git.remote_add(repo_path, "origin", repo_url, overwrite=True)
```

## Git configuration

You can set and read Git configuration items. If you want to configure the submission author, please refer to [Configuring Submission Identity](#Configuration Submission Identity).

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()
repo_path = "/home/user/repo"

# Global configuration
sandbox.git.set_config("pull.rebase", "false")
rebase = sandbox.git.get_config("pull.rebase")

# Warehouse local configuration
sandbox.git.set_config("pull.rebase", "false", scope="local", path=repo_path)
local_rebase = sandbox.git.get_config("pull.rebase", scope="local", path=repo_path)
```
