Skip to content

Commit 77b08f5

Browse files
Feature: Add Git Support (#1101)
# Sandbox Git Commands Adds Git support to the sandbox class. This allows the sandbox to manage git via standard clone, checkout, branch, add, pull, and push commands without needing to use commands.run. The API mirrors common Git workflows while handling sandbox-specific concerns like auth injection and safe remote handling. **Python example** ```python from e2b import Sandbox sandbox = Sandbox.create() repo_path = '/home/user/my-repo' # Optional: set author for commits sandbox.git.configure_user('Your Name', 'you@example.com') # Clone or init sandbox.git.clone('https://github.com/org/repo.git', path=repo_path) # or sandbox.git.init(repo_path, initial_branch='main') # Make a change sandbox.files.write(f'{repo_path}/README.md', '# Hello\n') # Commit sandbox.git.add(repo_path, files=['README.md']) sandbox.git.commit(repo_path, message='Initial commit') # Branching sandbox.git.create_branch(repo_path, 'feature1') # or sandbox.git.checkout_branch(repo_path, 'main') # Push sandbox.git.remote_add(repo_path, 'origin', 'https://github.com/org/repo.git', overwrite=True) sandbox.git.push(repo_path, remote='origin', branch='main', set_upstream=True) ``` **JavaScript / TypeScript example** ```ts import { Sandbox } from 'e2b' const sandbox = await Sandbox.create() const repoPath = '/home/user/my-repo' await sandbox.git.configureUser('Your Name', 'you@example.com') await sandbox.git.clone('https://github.com/org/repo.git', { path: repoPath }) // or await sandbox.git.init(repoPath, { initialBranch: 'main' }) await sandbox.files.write(`${repoPath}/README.md`, '# Hello\n') await sandbox.git.add(repoPath, { files: ['README.md'] }) await sandbox.git.commit(repoPath, { message: 'Initial commit' }) await sandbox.git.createBranch(repoPath, 'feature1') await sandbox.git.checkoutBranch(repoPath, 'main') await sandbox.git.remoteAdd(repoPath, 'origin', 'https://github.com/org/repo.git', { overwrite: true, }) await sandbox.git.push(repoPath, { remote: 'origin', branch: 'main', setUpstream: true }) ``` **Main commands** - `clone`: Clone a repo into the sandbox. Supports `branch`, `depth`, optional `username` + `password` for private repos, and `dangerously_store_credentials` / `dangerouslyStoreCredentials` to keep credentials in the remote URL. - `init`: Initialize a new repo. Supports `initial_branch` / `initialBranch` and `bare`. - `status`: Get parsed `git status --porcelain -b` info. - `branches`: List branches and current branch. - `create_branch` / `createBranch`: Create and check out a new branch. - `checkout_branch` / `checkoutBranch`: Switch to an existing branch. - `delete_branch` / `deleteBranch`: Delete a branch. Supports `force`. - `add`: Stage files. Supports explicit files or `all`. - `commit`: Create a commit. Supports author override and `allow_empty`. - `reset` / `reset`: Reset `HEAD` (supports modes like `soft`, `mixed`, `hard`, etc.) and optional paths. - `restore` / `restore`: Restore files or unstage changes (`worktree` / `staged`) from a source ref. - `pull`: Pull from a remote. Supports `remote`, `branch`, and optional auth. - `push`: Push to a remote. Supports `remote`, `branch`, `set_upstream`, and optional auth. - `remote_add` / `remoteAdd`: Add a remote. Supports `overwrite` and `fetch`. - `remote_get` / `remoteGet`: Read a remote URL. - `set_config` / `setConfig`: Set a git config value. Supports `scope` (`global`, `local`, `system`), and `path` for local scope. - `get_config` / `getConfig`: Read a git config value. Supports the same `scope` options and returns `None` / `undefined` if unset. - `dangerously_authenticate` / `dangerouslyAuthenticate`: Persist credentials via the git credential helper (global). - `configure_user` / `configureUser`: Set default `user.name` and `user.email` for commits. - `create_github_repo` (Python only): Create a GitHub repo from inside the sandbox and optionally add it as a remote. **Status shape** - `status` returns a `GitStatus` with `current_branch` / `currentBranch`, `upstream`, `ahead`, `behind`, `detached`, and `file_status` / `fileStatus`. - `file_status` entries include `name`, `status`, `index_status` / `indexStatus`, `working_tree_status` / `workingTreeStatus`, `staged`, and optional `renamed_from` / `renamedFrom`. - Convenience helpers include: `is_clean` / `isClean`, `has_changes` / `hasChanges`, `has_staged` / `hasStaged`, `has_untracked` / `hasUntracked`, `has_conflicts` / `hasConflicts`, plus counts (`total_count` / `totalCount`, `staged_count` / `stagedCount`, `unstaged_count` / `unstagedCount`, `untracked_count` / `untrackedCount`, `conflict_count` / `conflictCount`). In Python these are properties on the `GitStatus` object; in JS they are fields on the returned object. **Notes** - For private HTTPS remotes, pass `username` + `password` (token) on `clone`, `pull`, or `push`. - Use `remote_add` / `remoteAdd` with `overwrite=True` to update an existing remote URL and `fetch=True` to fetch after. - Use `dangerously_authenticate` / `dangerouslyAuthenticate` only when you want to persist credentials globally on the sandbox.
1 parent b2ea21c commit 77b08f5

40 files changed

+5874
-0
lines changed

.changeset/odd-drinks-walk.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@e2b/python-sdk': minor
3+
'e2b': minor
4+
---
5+
6+
Adds first class support to git commands to the sandbox sdk.

packages/js-sdk/src/errors.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,26 @@ export class AuthenticationError extends Error {
7878
}
7979
}
8080

81+
/**
82+
* Thrown when git authentication fails.
83+
*/
84+
export class GitAuthError extends AuthenticationError {
85+
constructor(message: string) {
86+
super(message)
87+
this.name = 'GitAuthError'
88+
}
89+
}
90+
91+
/**
92+
* Thrown when git upstream tracking is missing.
93+
*/
94+
export class GitUpstreamError extends SandboxError {
95+
constructor(message: string, stackTrace?: string) {
96+
super(message, stackTrace)
97+
this.name = 'GitUpstreamError'
98+
}
99+
}
100+
81101
/**
82102
* Thrown when the template uses old envd version. It isn't compatible with the new SDK.
83103
*/

packages/js-sdk/src/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export { ConnectionConfig } from './connectionConfig'
55
export type { ConnectionOpts, Username } from './connectionConfig'
66
export {
77
AuthenticationError,
8+
GitAuthError,
9+
GitUpstreamError,
810
InvalidArgumentError,
911
NotEnoughSpaceError,
1012
NotFoundError,
@@ -62,6 +64,25 @@ export type {
6264
Pty,
6365
} from './sandbox/commands'
6466

67+
export { Git } from './sandbox/git'
68+
export type {
69+
GitRequestOpts,
70+
GitCloneOpts,
71+
GitInitOpts,
72+
GitRemoteAddOpts,
73+
GitCommitOpts,
74+
GitAddOpts,
75+
GitDeleteBranchOpts,
76+
GitPushOpts,
77+
GitPullOpts,
78+
GitDangerouslyAuthenticateOpts,
79+
GitConfigOpts,
80+
GitConfigScope,
81+
GitBranches,
82+
GitFileStatus,
83+
GitStatus,
84+
} from './sandbox/git'
85+
6586
export { Sandbox }
6687
import { Sandbox } from './sandbox'
6788

0 commit comments

Comments
 (0)