Back to Daytona

Git Operations

apps/docs/src/content/docs/en/git-operations.mdx

0.176.017.5 KB
Original Source

import { TabItem, Tabs } from '@astrojs/starlight/components'

Daytona provides built-in Git support through the git module in sandboxes.

Basic operations

Daytona provides methods to clone, check status, and manage Git repositories in sandboxes.

Similar to file system operations, the starting cloning directory is the current sandbox working directory. It uses the WORKDIR specified in the Dockerfile if present, or falls back to the user's home directory if not - e.g. workspace/repo implies /my-work-dir/workspace/repo, but you are free to provide an absolute workDir path as well (by starting the path with /).

Clone repositories

Daytona provides methods to clone Git repositories into sandboxes. You can clone public or private repositories, specific branches, and authenticate using personal access tokens.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Basic clone
sandbox.git.clone(
    url="https://github.com/user/repo.git",
    path="workspace/repo"
)

# Clone with authentication
sandbox.git.clone(
    url="https://github.com/user/repo.git",
    path="workspace/repo",
    username="git",
    password="personal_access_token"
)

# Clone specific branch
sandbox.git.clone(
    url="https://github.com/user/repo.git",
    path="workspace/repo",
    branch="develop"
)
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Basic clone
await sandbox.git.clone(
    "https://github.com/user/repo.git",
    "workspace/repo"
);

// Clone with authentication
await sandbox.git.clone(
    "https://github.com/user/repo.git",
    "workspace/repo",
    undefined,
    undefined,
    "git",
    "personal_access_token"
);

// Clone specific branch
await sandbox.git.clone(
    "https://github.com/user/repo.git",
    "workspace/repo",
    "develop"
);
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Basic clone
sandbox.git.clone(
  url: 'https://github.com/user/repo.git',
  path: 'workspace/repo'
)

# Clone with authentication
sandbox.git.clone(
  url: 'https://github.com/user/repo.git',
  path: 'workspace/repo',
  username: 'git',
  password: 'personal_access_token'
)

# Clone specific branch
sandbox.git.clone(
  url: 'https://github.com/user/repo.git',
  path: 'workspace/repo',
  branch: 'develop'
)
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Basic clone
err := sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "workspace/repo")
if err != nil {
	log.Fatal(err)
}

// Clone with authentication
err = sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "workspace/repo",
	options.WithUsername("git"),
	options.WithPassword("personal_access_token"),
)
if err != nil {
	log.Fatal(err)
}

// Clone specific branch
err = sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "workspace/repo",
	options.WithBranch("develop"),
)
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="Java" icon="seti:java">
java
// Basic clone
sandbox.git.clone("https://github.com/user/repo.git", "workspace/repo");

// Clone with authentication
sandbox.git.clone(
    "https://github.com/user/repo.git",
    "workspace/repo",
    null,
    null,
    "git",
    "personal_access_token"
);

// Clone specific branch
sandbox.git.clone(
    "https://github.com/user/repo.git",
    "workspace/repo",
    "develop",
    null,
    null,
    null
);
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/clone' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "branch": "",
  "commit_id": "",
  "password": "",
  "path": "",
  "url": "",
  "username": ""
}'
</TabItem> </Tabs>

Get repository status

Daytona provides methods to check the status of Git repositories in sandboxes. You can get the current branch, modified files, number of commits ahead and behind main branch.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Get repository status
status = sandbox.git.status("workspace/repo")
print(f"Current branch: {status.current_branch}")
print(f"Commits ahead: {status.ahead}")
print(f"Commits behind: {status.behind}")
for file in status.file_status:
    print(f"File: {file.name}")

# List branches
response = sandbox.git.branches("workspace/repo")
for branch in response.branches:
    print(f"Branch: {branch}")
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Get repository status
const status = await sandbox.git.status("workspace/repo");
console.log(`Current branch: ${status.currentBranch}`);
console.log(`Commits ahead: ${status.ahead}`);
console.log(`Commits behind: ${status.behind}`);
status.fileStatus.forEach(file => {
    console.log(`File: ${file.name}`);
});

// List branches
const response = await sandbox.git.branches("workspace/repo");
response.branches.forEach(branch => {
    console.log(`Branch: ${branch}`);
});
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Get repository status
status = sandbox.git.status('workspace/repo')
puts "Current branch: #{status.current_branch}"
puts "Commits ahead: #{status.ahead}"
puts "Commits behind: #{status.behind}"
status.file_status.each do |file|
  puts "File: #{file.name}"
end

# List branches
response = sandbox.git.branches('workspace/repo')
response.branches.each do |branch|
  puts "Branch: #{branch}"
end
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Get repository status
status, err := sandbox.Git.Status(ctx, "workspace/repo")
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Current branch: %s\n", status.CurrentBranch)
fmt.Printf("Commits ahead: %d\n", status.Ahead)
fmt.Printf("Commits behind: %d\n", status.Behind)
for _, file := range status.FileStatus {
	fmt.Printf("File: %s\n", file.Path)
}

// List branches
branches, err := sandbox.Git.Branches(ctx, "workspace/repo")
if err != nil {
	log.Fatal(err)
}
for _, branch := range branches {
	fmt.Printf("Branch: %s\n", branch)
}
</TabItem> <TabItem label="Java" icon="seti:java">
java
import io.daytona.sdk.model.GitStatus;
import java.util.List;

// Get repository status
GitStatus status = sandbox.git.status("workspace/repo");
System.out.println("Current branch: " + status.getCurrentBranch());
System.out.println("Commits ahead: " + status.getAhead());
System.out.println("Commits behind: " + status.getBehind());
for (GitStatus.FileStatus file : status.getFileStatus()) {
    System.out.println("File: " + file.getPath());
}

// List branches
Object rawBranches = sandbox.git.branches("workspace/repo").get("branches");
if (rawBranches instanceof List<?> branchList) {
    for (Object branch : branchList) {
        System.out.println("Branch: " + branch);
    }
}
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/status?path='
</TabItem> </Tabs>

Branch operations

Daytona provides methods to manage branches in Git repositories. You can create, switch, and delete branches.

Create branches

Daytona provides methods to create branches in Git repositories. The following snippet creates a new branch called new-feature.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Create a new branch
sandbox.git.create_branch("workspace/repo", "new-feature")
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Create new branch
await git.createBranch('workspace/repo', 'new-feature');
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Create a new branch
sandbox.git.create_branch('workspace/repo', 'new-feature')
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Create a new branch
err := sandbox.Git.CreateBranch(ctx, "workspace/repo", "new-feature")
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/branches' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "",
  "path": ""
}'
</TabItem> </Tabs>

Checkout branches

Daytona provides methods to checkout branches in Git repositories. The following snippet checks out the branch called feature-branch.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Checkout a branch
sandbox.git.checkout_branch("workspace/repo", "feature-branch")
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Checkout a branch
await git.checkoutBranch('workspace/repo', 'feature-branch');
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Checkout a branch
sandbox.git.checkout_branch('workspace/repo', 'feature-branch')
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Checkout a branch
err := sandbox.Git.Checkout(ctx, "workspace/repo", "feature-branch")
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/checkout' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "branch": "",
  "path": ""
}'
</TabItem> </Tabs>

Delete branches

Daytona provides methods to delete branches in Git repositories. The following snippet deletes the branch called old-feature.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Delete a branch
sandbox.git.delete_branch("workspace/repo", "old-feature")
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Delete a branch
await git.deleteBranch('workspace/repo', 'old-feature');
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Delete a branch
sandbox.git.delete_branch('workspace/repo', 'old-feature')
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Delete a branch
err := sandbox.Git.DeleteBranch(ctx, "workspace/repo", "old-feature")
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/branches' \
  --request DELETE \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "",
  "path": ""
}'
</TabItem> </Tabs>

Stage changes

Daytona provides methods to stage changes in Git repositories. You can stage specific files, all changes, and commit with a message. The following snippet stages the file file.txt and the src directory.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Stage a single file
sandbox.git.add("workspace/repo", ["file.txt"])

# Stage multiple files
sandbox.git.add("workspace/repo", [
    "src/main.py",
    "tests/test_main.py",
    "README.md"
])
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Stage a single file
await git.add('workspace/repo', ['file.txt']);
// Stage whole repository
await git.add('workspace/repo', ['.']);
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Stage a single file
sandbox.git.add('workspace/repo', ['file.txt'])
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Stage a single file
err := sandbox.Git.Add(ctx, "workspace/repo", []string{"file.txt"})
if err != nil {
	log.Fatal(err)
}

// Stage multiple files
err = sandbox.Git.Add(ctx, "workspace/repo", []string{
	"src/main.py",
	"tests/test_main.py",
	"README.md",
})
if err != nil {
	log.Fatal(err)
}

// Stage whole repository
err = sandbox.Git.Add(ctx, "workspace/repo", []string{"."})
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="Java" icon="seti:java">
java
import java.util.List;

// Stage a single file
sandbox.git.add("workspace/repo", List.of("file.txt"));

// Stage multiple files
sandbox.git.add(
    "workspace/repo",
    List.of("src/main.py", "tests/test_main.py", "README.md")
);

// Stage whole repository
sandbox.git.add("workspace/repo", List.of("."));
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/add' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "files": [
    ""
  ],
  "path": ""
}'
</TabItem> </Tabs>

Commit changes

Daytona provides methods to commit changes in Git repositories. You can commit with a message, author, and email. The following snippet commits the changes with the message Update documentation and the author John Doe and email [email protected].

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Stage and commit changes
sandbox.git.add("workspace/repo", ["README.md"])
sandbox.git.commit(
    path="workspace/repo",
    message="Update documentation",
    author="John Doe",
    email="[email protected]",
    allow_empty=True
)
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Stage and commit changes
await git.add('workspace/repo', ['README.md']);
await git.commit(
  'workspace/repo',
  'Update documentation',
  'John Doe',
  '[email protected]',
  true
);
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Stage and commit changes
sandbox.git.add('workspace/repo', ['README.md'])
sandbox.git.commit('workspace/repo', 'Update documentation', 'John Doe', '[email protected]', true)
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Stage and commit changes
err := sandbox.Git.Add(ctx, "workspace/repo", []string{"README.md"})
if err != nil {
	log.Fatal(err)
}

response, err := sandbox.Git.Commit(ctx, "workspace/repo",
	"Update documentation",
	"John Doe",
	"[email protected]",
	options.WithAllowEmpty(true),
)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Commit SHA: %s\n", response.SHA)
</TabItem> <TabItem label="Java" icon="seti:java">
java
import io.daytona.sdk.model.GitCommitResponse;
import java.util.List;

// Stage and commit changes
sandbox.git.add("workspace/repo", List.of("README.md"));
GitCommitResponse response = sandbox.git.commit(
    "workspace/repo",
    "Update documentation",
    "John Doe",
    "[email protected]"
);
System.out.println("Commit hash: " + response.getHash());
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/commit' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "allow_empty": true,
  "author": "",
  "email": "",
  "message": "",
  "path": ""
}'
</TabItem> </Tabs>

Remote operations

Daytona provides methods to work with remote repositories in Git. You can push and pull changes from remote repositories.

Push changes

Daytona provides methods to push changes to remote repositories. The following snippet pushes the changes to a public repository.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Push without authentication (for public repos or SSH)
sandbox.git.push("workspace/repo")

# Push with authentication
sandbox.git.push(
    path="workspace/repo",
    username="user",
    password="github_token"
)
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Push to a public repository
await git.push('workspace/repo');

// Push to a private repository
await git.push(
  'workspace/repo',
  'user',
  'token'
);
</TabItem> <TabItem label="Ruby" icon="seti:ruby"> ```ruby # Push changes sandbox.git.push('workspace/repo') ``` </TabItem> <TabItem label="Go" icon="seti:go">
go
// Push without authentication (for public repos or SSH)
err := sandbox.Git.Push(ctx, "workspace/repo")
if err != nil {
	log.Fatal(err)
}

// Push with authentication
err = sandbox.Git.Push(ctx, "workspace/repo",
	options.WithPushUsername("user"),
	options.WithPushPassword("github_token"),
)
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="Java" icon="seti:java">
java
// Push without authentication (for public repos or SSH)
sandbox.git.push("workspace/repo");
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/push' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "password": "",
  "path": "",
  "username": ""
}'
</TabItem> </Tabs>

Pull changes

Daytona provides methods to pull changes from remote repositories. The following snippet pulls the changes from a public repository.

<Tabs syncKey="language"> <TabItem label="Python" icon="seti:python">
python
# Pull without authentication
sandbox.git.pull("workspace/repo")

# Pull with authentication
sandbox.git.pull(
    path="workspace/repo",
    username="user",
    password="github_token"
)
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
typescript
// Pull from a public repository
await git.pull('workspace/repo');

// Pull from a private repository
await git.pull(
  'workspace/repo',
  'user',
  'token'
);
</TabItem> <TabItem label="Ruby" icon="seti:ruby">
ruby
# Pull changes
sandbox.git.pull('workspace/repo')
</TabItem> <TabItem label="Go" icon="seti:go">
go
// Pull without authentication
err := sandbox.Git.Pull(ctx, "workspace/repo")
if err != nil {
	log.Fatal(err)
}

// Pull with authentication
err = sandbox.Git.Pull(ctx, "workspace/repo",
	options.WithPullUsername("user"),
	options.WithPullPassword("github_token"),
)
if err != nil {
	log.Fatal(err)
}
</TabItem> <TabItem label="Java" icon="seti:java">
java
// Pull without authentication
sandbox.git.pull("workspace/repo");
</TabItem> <TabItem label="API" icon="seti:json">
bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/pull' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "password": "",
  "path": "",
  "username": ""
}'
</TabItem> </Tabs>