AsyncGit | Daytona
AsyncGit
class AsyncGit()
Provides Git operations within a Sandbox.
Example:
# Clone a repository
await sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Check repository status
status = await sandbox.git.status("workspace/repo")
print(f"Modified files: {status.modified}")
# Stage and commit changes
await sandbox.git.add("workspace/repo", ["file.txt"])
await sandbox.git.commit(
path="workspace/repo",
message="Update file",
author="John Doe",
email="john@example.com"
)
AsyncGit.init
def __init__(api_client: GitApi)
Initializes a new Git handler instance.
Arguments:
api_clientGitApi - API client for Sandbox Git operations.
AsyncGit.add
@intercept_errors(message_prefix="Failed to add files: ")
@with_instrumentation()
async def add(path: str,
files: list[str],
request_timeout: float | None = None) -> None
Stages the specified files for the next commit, similar to running ‘git add’ on the command line.
Arguments:
pathstr - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.fileslist[str] - List of file paths or directories to stage, relative to the repository root.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Stage a single file
await sandbox.git.add("workspace/repo", ["file.txt"])
# Stage multiple files
await sandbox.git.add("workspace/repo", [
"src/main.py",
"tests/test_main.py",
"README.md"
])
AsyncGit.branches
@intercept_errors(message_prefix="Failed to list branches: ")
@with_instrumentation()
async def branches(path: str,
request_timeout: float | None = None) -> ListBranchResponse
Lists branches in the repository.
Arguments:
pathstr - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Returns:
ListBranchResponse- List of branches in the repository.
Example:
response = await sandbox.git.branches("workspace/repo")
print(f"Branches: {response.branches}")
AsyncGit.clone
@intercept_errors(message_prefix="Failed to clone repository: ")
@with_instrumentation()
async def clone(url: str,
path: str,
branch: str | None = None,
commit_id: str | None = None,
username: str | None = None,
password: str | None = None,
insecure_skip_tls: bool | None = None,
depth: int | None = None,
request_timeout: float | None = None) -> None
Clones a Git repository into the specified path.
Arguments:
urlstr - Repository URL to clone from.pathstr - Path where the repository should be cloned.branchstr | None - Specific branch to clone.commit_idstr | None - Specific commit to clone.usernamestr | None - Git username for authentication.passwordstr | None - Git password or token for authentication.insecure_skip_tlsbool | None - Skip TLS certificate verification.depthint | None - Create a shallow clone truncated to the given number of commits.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Clone the default branch
await sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Clone a specific branch with authentication
await sandbox.git.clone(
url="https://github.com/user/private-repo.git",
path="workspace/private",
branch="develop",
username="user",
password="token"
)
# Clone a specific commit
await sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo-old",
commit_id="abc123"
)
AsyncGit.commit
@intercept_errors(message_prefix="Failed to commit changes: ")
@with_instrumentation()
async def commit(path: str,
message: str,
author: str,
email: str,
allow_empty: bool = False,
request_timeout: float | None = None) -> GitCommitResponse
Creates a new commit with the staged changes.
Arguments:
pathstr - Path to the Git repository root.messagestr - Commit message describing the changes.authorstr - Name of the commit author.emailstr - Email address of the commit author.allow_emptybool - Allow creating an empty commit when no changes are staged.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Stage and commit changes
await sandbox.git.add("workspace/repo", ["README.md"])
await sandbox.git.commit(
path="workspace/repo",
message="Update documentation",
author="John Doe",
email="john@example.com",
allow_empty=True
)
AsyncGit.push
@intercept_errors(message_prefix="Failed to push changes: ")
@with_instrumentation()
async def push(path: str,
username: str | None = None,
password: str | None = None,
branch: str | None = None,
remote: str | None = None,
set_upstream: bool = False,
request_timeout: float | None = None) -> None
Pushes all local commits on the current branch to the remote repository.
Arguments:
pathstr - Path to the Git repository root.usernamestr | None - Git username for authentication.passwordstr | None - Git password or token for authentication.branchstr | None - Branch to push.remotestr | None - Remote to push to.set_upstreambool - Record the pushed branch as the upstream tracking branch.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Push without authentication (for public repos or SSH)
await sandbox.git.push("workspace/repo")
# Push with authentication
await sandbox.git.push(
path="workspace/repo",
username="user",
password="github_token"
)
# Push a new branch and set its upstream
await sandbox.git.push("workspace/repo", branch="feature", set_upstream=True)
AsyncGit.pull
@intercept_errors(message_prefix="Failed to pull changes: ")
@with_instrumentation()
async def pull(path: str,
username: str | None = None,
password: str | None = None,
branch: str | None = None,
remote: str | None = None,
request_timeout: float | None = None) -> None
Pulls changes from the remote repository.
Arguments:
pathstr - Path to the Git repository root.usernamestr | None - Git username for authentication.passwordstr | None - Git password or token for authentication.branchstr | None - Branch to pull.remotestr | None - Remote to pull from.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Pull without authentication
await sandbox.git.pull("workspace/repo")
# Pull with authentication
await sandbox.git.pull(
path="workspace/repo",
username="user",
password="github_token"
)
# Pull a specific branch from a specific remote
await sandbox.git.pull("workspace/repo", remote="upstream", branch="main")
AsyncGit.status
@intercept_errors(message_prefix="Failed to get status: ")
@with_instrumentation()
async def status(path: str, request_timeout: float | None = None) -> GitStatus
Gets the current Git repository status.
Arguments:
pathstr - Path to the Git repository root.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Returns:
GitStatus- Repository status information including:- current_branch: Current branch name
- file_status: List of file statuses
- ahead: Number of local commits not pushed to remote
- behind: Number of remote commits not pulled locally
- branch_published: Whether the branch has been published to the remote repository
Example:
status = await sandbox.git.status("workspace/repo")
print(f"On branch: {status.current_branch}")
print(f"Commits ahead: {status.ahead}")
print(f"Commits behind: {status.behind}")
AsyncGit.checkout_branch
@intercept_errors(message_prefix="Failed to checkout branch: ")
@with_instrumentation()
async def checkout_branch(path: str,
branch: str,
request_timeout: float | None = None) -> None
Checkout branch in the repository.
Arguments:
pathstr - Path to the Git repository root.branchstr - Name of the branch to checkoutrequest_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Checkout a branch
await sandbox.git.checkout_branch("workspace/repo", "feature-branch")
AsyncGit.create_branch
@intercept_errors(message_prefix="Failed to create branch: ")
@with_instrumentation()
async def create_branch(path: str,
name: str,
request_timeout: float | None = None) -> None
Create branch in the repository.
Arguments:
pathstr - Path to the Git repository root.namestr - Name of the new branch to createrequest_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Create a new branch
await sandbox.git.create_branch("workspace/repo", "new-feature")
AsyncGit.delete_branch
@intercept_errors(message_prefix="Failed to delete branch: ")
@with_instrumentation()
async def delete_branch(path: str,
name: str,
request_timeout: float | None = None) -> None
Delete branch in the repository.
Arguments:
pathstr - Path to the Git repository root.namestr - Name of the branch to deleterequest_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Delete a branch
await sandbox.git.delete_branch("workspace/repo", "old-feature")
AsyncGit.init
@intercept_errors(message_prefix="Failed to initialize repository: ")
@with_instrumentation()
async def init(path: str,
bare: bool = False,
initial_branch: str | None = None,
request_timeout: float | None = None) -> None
Initializes a new Git repository at the specified path.
Arguments:
pathstr - Path where the repository should be initialized.barebool, optional - Create a bare repository without a working tree.initial_branchstr | None - Name of the initial branch.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
await sandbox.git.init("workspace/repo", initial_branch="main")
AsyncGit.reset
@intercept_errors(message_prefix="Failed to reset: ")
@with_instrumentation()
async def reset(path: str,
mode: str | None = None,
target: str | None = None,
files: list[str] | None = None,
request_timeout: float | None = None) -> None
Resets the current HEAD to the specified state.
Arguments:
pathstr - Path to the Git repository root.modestr | None - Reset mode.targetstr | None - Revision to reset to.fileslist[str] | None - Constrain the reset to the given paths.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Unstage all changes (mixed reset to HEAD)
await sandbox.git.reset("workspace/repo")
# Hard reset to a previous commit
await sandbox.git.reset("workspace/repo", mode="hard", target="HEAD~1")
AsyncGit.restore
@intercept_errors(message_prefix="Failed to restore files: ")
@with_instrumentation()
async def restore(path: str,
files: list[str],
staged: bool | None = None,
worktree: bool | None = None,
source: str | None = None,
request_timeout: float | None = None) -> None
Restores working tree files or unstages changes.
Arguments:
pathstr - Path to the Git repository root.fileslist[str] - File paths to restore.stagedbool | None - Restore the staging index for the given files.worktreebool | None - Restore the working tree for the given files.sourcestr | None - Restore file contents from the given revision instead of the index.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
# Discard working tree changes
await sandbox.git.restore("workspace/repo", ["file.txt"])
# Unstage changes
await sandbox.git.restore("workspace/repo", ["file.txt"], staged=True)
AsyncGit.remote_add
@intercept_errors(message_prefix="Failed to add remote: ")
@with_instrumentation()
async def remote_add(path: str,
name: str,
url: str,
fetch: bool = False,
overwrite: bool = False,
request_timeout: float | None = None) -> None
Adds (or overwrites) a remote in the repository.
Arguments:
pathstr - Path to the Git repository root.namestr - Name of the remote.urlstr - URL of the remote.fetchbool, optional - Fetch from the remote immediately after adding it.overwritebool, optional - Replace an existing remote with the same name.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
await sandbox.git.remote_add("workspace/repo", "origin", "https://github.com/user/repo.git")
AsyncGit.remotes
@intercept_errors(message_prefix="Failed to list remotes: ")
@with_instrumentation()
async def remotes(path: str,
request_timeout: float | None = None) -> ListRemotesResponse
Lists the remotes configured in the repository.
Arguments:
pathstr - Path to the Git repository root.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Returns:
ListRemotesResponse- The configured remotes (name + URL).
Example:
response = await sandbox.git.remotes("workspace/repo")
for remote in response.remotes:
print(f"{remote.name}: {remote.url}")
AsyncGit.remote_get
@intercept_errors(message_prefix="Failed to get remote: ")
@with_instrumentation()
async def remote_get(path: str,
name: str,
request_timeout: float | None = None) -> str | None
Gets the URL of a remote, or None when it does not exist.
Arguments:
pathstr - Path to the Git repository root.namestr - Name of the remote.request_timeoutfloat | None - Optional client-side request timeout in seconds.
Returns:
- str | None: The remote URL, or None when the remote does not exist.
Example:
url = await sandbox.git.remote_get("workspace/repo", "origin")
AsyncGit.set_config
@intercept_errors(message_prefix="Failed to set config: ")
@with_instrumentation()
async def set_config(key: str,
value: str,
scope: str = "global",
path: str | None = None,
request_timeout: float | None = None) -> None
Sets a Git config value at the given scope.
Arguments:
keystr - Config key in dotted form (e.g. "user.name").valuestr - Config value.scopestr, optional - Config scope, one of "global" (default), "local" or "system".pathstr | None - Repository path, required when scope is "local".request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
await sandbox.git.set_config("user.name", "John Doe")
AsyncGit.get_config
@intercept_errors(message_prefix="Failed to get config: ")
@with_instrumentation()
async def get_config(key: str,
scope: str = "global",
path: str | None = None,
request_timeout: float | None = None) -> str | None
Gets a Git config value at the given scope, or None when unset.
Arguments:
keystr - Config key in dotted form (e.g. "user.name").scopestr, optional - Config scope, one of "global" (default), "local" or "system".pathstr | None - Repository path, required when scope is "local".request_timeoutfloat | None - Optional client-side request timeout in seconds.
Returns:
- str | None: The config value, or None when the key is not set.
Example:
name = await sandbox.git.get_config("user.name")
AsyncGit.configure_user
@intercept_errors(message_prefix="Failed to configure user: ")
@with_instrumentation()
async def configure_user(name: str,
email: str,
scope: str = "global",
path: str | None = None,
request_timeout: float | None = None) -> None
Configures the Git user name and email at the given scope.
Arguments:
namestr - User name (user.name).emailstr - User email (user.email).scopestr, optional - Config scope, one of "global" (default), "local" or "system".pathstr | None - Repository path, required when scope is "local".request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
await sandbox.git.configure_user("John Doe", "john@example.com")
AsyncGit.dangerously_authenticate
@intercept_errors(message_prefix="Failed to authenticate: ")
@with_instrumentation()
async def dangerously_authenticate(
username: str,
password: str,
host: str | None = None,
protocol: str | None = None,
request_timeout: float | None = None) -> None
Persists Git credentials globally so that subsequent operations against the given host authenticate automatically.
Arguments:
usernamestr - Git username.passwordstr - Git password or token.hoststr | None - Host to authenticate against. Defaults to "github.com".protocolstr | None - Protocol to authenticate against. Defaults to "https".request_timeoutfloat | None - Optional client-side request timeout in seconds.
Example:
await sandbox.git.dangerously_authenticate("user", "github_token")
GitCommitResponse
class GitCommitResponse()
Response from the git commit.
Attributes:
shastr - The SHA of the commit.