CtrlK
BlogDocsLog inGet started
Tessl Logo

finkel/jgit

JGit documentation and API reference with code examples

92

1.09x
Quality

Pending

Does it follow best practices?

Impact

92%

1.09x

Average score across 10 eval scenarios

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/remote/

Remote Operations

JGit provides comprehensive support for working with remote Git repositories, including cloning, fetching, pushing, and managing remote references.

Table of Contents

  1. Cloning Repositories
  2. Fetching Changes
  3. Pushing Changes
  4. Managing Remotes
  5. Authentication
  6. In-Memory Repositories
  7. GitHub Integration

Cloning Repositories

Clone a Remote Repository

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import java.io.File;

public class CloneRepositoryExample {
    public static void main(String[] args) throws GitAPIException {
        String remoteUrl = "https://github.com/example/repo.git";
        File localDir = new File("/path/to/local/clone");

        // Basic clone
        try (Git git = Git.cloneRepository()
                .setURI(remoteUrl)
                .setDirectory(localDir)
                .call()) {

            System.out.println("Repository cloned to: " + localDir.getAbsolutePath());
            System.out.println("Branch: " + git.getRepository().getBranch());
        }
    }
}

Clone with Authentication

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import java.io.File;

public class CloneWithAuthExample {
    public static void main(String[] args) throws GitAPIException {
        String remoteUrl = "https://github.com/example/private-repo.git";
        File localDir = new File("/path/to/local/clone");
        String username = "your-username";
        String password = "your-password"; // or personal access token

        try (Git git = Git.cloneRepository()
                .setURI(remoteUrl)
                .setDirectory(localDir)
                .setCredentialsProvider(
                    new UsernamePasswordCredentialsProvider(username, password))
                .call()) {

            System.out.println("Private repository cloned successfully");
        }
    }
}

Clone via SSH

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.util.FS;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.io.File;

public class CloneViaSshExample {
    public static void main(String[] args) throws GitAPIException {
        // Configure SSH session factory
        SshSessionFactory.setInstance(new JschConfigSessionFactory() {
            @Override
            protected void configure(OpenSshConfig.Host host, Session session) {
                // Configure SSH session (e.g., set identity file)
            }

            @Override
            protected JSch createDefaultJSch(FS fs) throws JSchException {
                JSch defaultJSch = super.createDefaultJSch(fs);
                // Add private key
                defaultJSch.addIdentity("/path/to/private/key");
                return defaultJSch;
            }
        });

        String sshUrl = "git@github.com:example/repo.git";
        File localDir = new File("/path/to/local/clone");

        try (Git git = Git.cloneRepository()
                .setURI(sshUrl)
                .setDirectory(localDir)
                .call()) {

            System.out.println("Repository cloned via SSH");
        }
    }
}

Fetching Changes

Fetch from Remote

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.FetchResult;
import java.io.IOException;

public class FetchFromRemoteExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Fetch from all remotes
                FetchResult result = git.fetch()
                    .call();

                System.out.println("Fetch completed");
                System.out.println("Tracking ref updates: " + result.getTrackingRefUpdates());
                System.out.println("Advertised refs: " + result.getAdvertisedRefs());
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Fetch with Prune

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class FetchWithPruneExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Fetch and prune outdated remote branches
                git.fetch()
                    .setRemoveDeletedRefs(true) // Prune deleted remote branches
                    .call();

                System.out.println("Fetch with prune completed");
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Pushing Changes

Push to Remote Repository

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import java.io.IOException;
import java.util.Collection;

public class PushToRemoteExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Push changes to remote
                Iterable<PushResult> results = git.push()
                    .setRemote("origin")
                    .setForce(false) // Don't force push
                    .call();

                for (PushResult result : results) {
                    Collection<RemoteRefUpdate> updates = result.getRemoteUpdates();
                    System.out.println("Push results:");
                    for (RemoteRefUpdate update : updates) {
                        System.out.println("  " + update.getRemoteName() + ": " +
                                         update.getStatus());
                    }
                }
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Push Specific Branch

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class PushSpecificBranchExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Push specific branch to remote
                git.push()
                    .setRemote("origin")
                    .add("feature/new-feature") // Branch to push
                    .call();

                System.out.println("Branch pushed to remote");
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Managing Remotes

List Remote Repositories

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.RemoteConfig;
import java.io.IOException;
import java.util.List;

public class ListRemotesExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // List all remote configurations
                List<RemoteConfig> remotes = git.remoteList()
                    .call();

                System.out.println("Configured remotes:");
                for (RemoteConfig remote : remotes) {
                    System.out.println("  Name: " + remote.getName());
                    System.out.println("  URLs: " + remote.getURIs());
                    System.out.println("  Push URLs: " + remote.getPushURIs());
                }
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Add Remote Repository

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class AddRemoteExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Add a new remote
                git.remoteAdd()
                    .setName("upstream")
                    .setUri(new URIish("https://github.com/upstream/repo.git"))
                    .call();

                System.out.println("Added remote 'upstream'");
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Remove Remote Repository

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class RemoveRemoteExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Remove a remote
                git.remoteRemove()
                    .setRemoteName("old-remote")
                    .call();

                System.out.println("Removed remote 'old-remote'");
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Authentication

HTTP Authentication

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import java.io.File;

public class HttpAuthenticationExample {
    public static void main(String[] args) throws GitAPIException {
        String remoteUrl = "https://git.example.com/repo.git";
        File localDir = new File("/path/to/local/clone");

        // Using username/password
        var credentials = new UsernamePasswordCredentialsProvider(
            "username", "password");

        try (Git git = Git.cloneRepository()
                .setURI(remoteUrl)
                .setDirectory(localDir)
                .setCredentialsProvider(credentials)
                .call()) {

            System.out.println("Repository cloned with HTTP authentication");
        }
    }
}

SSH Key Authentication

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.util.FS;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.io.File;

public class SshKeyAuthenticationExample {
    public static void main(String[] args) throws GitAPIException {
        SshSessionFactory.setInstance(new JschConfigSessionFactory() {
            @Override
            protected void configure(OpenSshConfig.Host host, Session session) {
                // Configure session options
                session.setConfig("StrictHostKeyChecking", "no");
            }

            @Override
            protected JSch createDefaultJSch(FS fs) throws JSchException {
                JSch jsch = super.createDefaultJSch(fs);
                // Add multiple identity files
                jsch.addIdentity("/home/user/.ssh/id_rsa");
                jsch.addIdentity("/home/user/.ssh/id_ed25519");
                return jsch;
            }
        });

        String sshUrl = "git@github.com:example/repo.git";
        File localDir = new File("/path/to/local/clone");

        try (Git git = Git.cloneRepository()
                .setURI(sshUrl)
                .setDirectory(localDir)
                .call()) {

            System.out.println("Repository cloned with SSH key authentication");
        }
    }
}

In-Memory Repositories

Clone into Memory

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import java.io.File;
import java.io.IOException;

public class CloneIntoMemoryExample {
    public static void main(String[] args) throws IOException, GitAPIException {
        String remoteUrl = "https://github.com/example/small-repo.git";

        // Create an in-memory repository
        try (Repository repository = new FileRepositoryBuilder()
                .setGitDir(File.createTempFile("jgit", ".git"))
                .build()) {

            // Clone into the in-memory repository
            try (Git git = new Git(repository)) {
                git.cloneRepository()
                    .setURI(remoteUrl)
                    .setDirectory(null) // No working directory for bare clone
                    .setBare(true)
                    .call();

                System.out.println("Repository cloned into memory");
                System.out.println("Total objects: " + repository.getObjectDatabase().getObjectCount());
            }
        }
    }
}

GitHub Integration

Checkout GitHub Pull Request

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class CheckoutGitHubPullRequest {
    public static void main(String[] args) throws IOException, GitAPIException {
        try (Repository repository = openRepository()) {
            try (Git git = new Git(repository)) {
                // Fetch pull request refs
                git.fetch()
                    .setRemote("origin")
                    .setRefSpecs("+refs/pull/*/head:refs/remotes/origin/pr/*")
                    .call();

                // Checkout specific pull request
                int prNumber = 123;
                git.checkout()
                    .setName("origin/pr/" + prNumber)
                    .setCreateBranch(true)
                    .setStartPoint("origin/pr/" + prNumber)
                    .setForce(true)
                    .call();

                System.out.println("Checked out PR #" + prNumber);
            }
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Best Practices

Error Handling for Remote Operations

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class RemoteErrorHandling {
    public static void safePush(Repository repository) {
        try (Git git = new Git(repository)) {
            git.push()
                .setRemote("origin")
                .setForce(false)
                .call();
        } catch (TransportException e) {
            System.err.println("Network error during push: " + e.getMessage());
            // Handle network issues
        } catch (GitAPIException e) {
            System.err.println("Git error during push: " + e.getMessage());
            // Handle Git-specific errors
        } catch (Exception e) {
            System.err.println("Unexpected error: " + e.getMessage());
        }
    }

    public static void main(String[] args) throws IOException {
        try (Repository repository = openRepository()) {
            safePush(repository);
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Retry Pattern for Network Operations

Network operations often fail due to transient issues. Implementing retry logic with exponential backoff improves reliability.

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class RemoteRetryPattern {
    
    /**
     * Execute operation with exponential backoff retry
     */
    public static <T> T executeWithRetry(
            Callable<T> operation,
            int maxRetries,
            long initialDelayMs,
            Class<? extends Exception>... retryableExceptions) throws Exception {
        
        Exception lastException = null;
        
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                return operation.call();
            } catch (Exception e) {
                lastException = e;
                
                // Check if exception is retryable
                boolean shouldRetry = false;
                for (Class<? extends Exception> retryable : retryableExceptions) {
                    if (retryable.isInstance(e)) {
                        shouldRetry = true;
                        break;
                    }
                }
                
                if (!shouldRetry || attempt == maxRetries) {
                    break;
                }
                
                // Exponential backoff
                long delay = initialDelayMs * (1L << (attempt - 1));
                System.out.println("Attempt " + attempt + " failed, retrying in " +
                                 delay + "ms: " + e.getMessage());
                
                try {
                    TimeUnit.MILLISECONDS.sleep(delay);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new IOException("Interrupted during retry", ie);
                }
            }
        }
        
        throw lastException;
    }
    
    /**
     * Fetch with retry for network issues
     */
    public static void fetchWithRetry(Repository repository) throws Exception {
        executeWithRetry(() -> {
            try (Git git = new Git(repository)) {
                git.fetch().call();
                return null;
            }
        }, 3, 1000, TransportException.class);
    }
    
    /**
     * Push with retry and authentication handling
     */
    public static void pushWithRetry(Repository repository) throws Exception {
        executeWithRetry(() -> {
            try (Git git = new Git(repository)) {
                git.push()
                    .setRemote("origin")
                    .setForce(false)
                    .call();
                return null;
            }
        }, 3, 1000, TransportException.class);
    }
}

Error Handler Pattern

For complex applications, use a structured error handler pattern to separate error handling from business logic.

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.TransportException;
import java.util.function.Supplier;

public class RemoteErrorHandlerPattern {
    
    public enum RemoteOperation {
        CLONE, PUSH, PULL, FETCH
    }
    
    /**
     * Execute remote operation with comprehensive error handling
     */
    public static <T> T executeRemoteOperation(
            RemoteOperation operation,
            Supplier<T> operationSupplier,
            RemoteErrorHandler<T> errorHandler) {
        
        try {
            return operationSupplier.get();
        } catch (TransportException e) {
            return errorHandler.handleTransportError(operation, e);
        } catch (GitAPIException e) {
            return errorHandler.handleGitApiError(operation, e);
        } catch (Exception e) {
            return errorHandler.handleUnexpectedError(operation, e);
        }
    }
    
    public interface RemoteErrorHandler<T> {
        T handleTransportError(RemoteOperation operation, TransportException e);
        T handleGitApiError(RemoteOperation operation, GitAPIException e);
        T handleUnexpectedError(RemoteOperation operation, Exception e);
    }
    
    /**
     * Example error handler implementation
     */
    public static class LoggingRemoteErrorHandler<T> implements RemoteErrorHandler<T> {
        private final T defaultValue;
        
        public LoggingRemoteErrorHandler(T defaultValue) {
            this.defaultValue = defaultValue;
        }
        
        @Override
        public T handleTransportError(RemoteOperation operation, TransportException e) {
            System.err.println("Network error during " + operation + ": " + e.getMessage());
            // Log metrics, alert on repeated failures, etc.
            return defaultValue;
        }
        
        @Override
        public T handleGitApiError(RemoteOperation operation, GitAPIException e) {
            System.err.println("Git error during " + operation + ": " + e.getMessage());
            // Check for authentication errors, permission issues, etc.
            return defaultValue;
        }
        
        @Override
        public T handleUnexpectedError(RemoteOperation operation, Exception e) {
            System.err.println("Unexpected error during " + operation + ": " + e.getMessage());
            e.printStackTrace();
            return defaultValue;
        }
    }
}

Circuit Breaker Pattern

Prevent cascading failures by implementing a circuit breaker that stops attempting remote operations after repeated failures.

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class CircuitBreaker {
    
    private final AtomicInteger failureCount = new AtomicInteger(0);
    private final AtomicReference<Instant> lastFailureTime = new AtomicReference<>();
    private final int failureThreshold;
    private final Duration resetTimeout;
    private volatile boolean circuitOpen = false;
    
    public CircuitBreaker(int failureThreshold, Duration resetTimeout) {
        this.failureThreshold = failureThreshold;
        this.resetTimeout = resetTimeout;
    }
    
    public <T> T execute(Repository repository, GitOperation<T> operation) throws Exception {
        if (circuitOpen) {
            if (shouldTryReset()) {
                circuitOpen = false;
                failureCount.set(0);
            } else {
                throw new IOException("Circuit breaker is open - remote operations disabled");
            }
        }
        
        try {
            T result = operation.execute(repository);
            // Success - reset failure count
            failureCount.set(0);
            return result;
        } catch (Exception e) {
            handleFailure();
            throw e;
        }
    }
    
    private void handleFailure() {
        failureCount.incrementAndGet();
        lastFailureTime.set(Instant.now());
        
        if (failureCount.get() >= failureThreshold) {
            circuitOpen = true;
            System.err.println("Circuit breaker opened after " + failureCount.get() + " failures");
        }
    }
    
    private boolean shouldTryReset() {
        Instant lastFailure = lastFailureTime.get();
        if (lastFailure == null) return true;
        
        Duration timeSinceFailure = Duration.between(lastFailure, Instant.now());
        return timeSinceFailure.compareTo(resetTimeout) > 0;
    }
    
    @FunctionalInterface
    public interface GitOperation<T> {
        T execute(Repository repository) throws Exception;
    }
}

Concurrent Remote Operations

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ConcurrentRemoteOperations {
    public static void main(String[] args) throws IOException, InterruptedException {
        try (Repository repository = openRepository()) {
            ExecutorService executor = Executors.newFixedThreadPool(3);

            // Submit multiple remote operations
            executor.submit(() -> {
                try (Git git = new Git(repository)) {
                    git.fetch().call();
                    System.out.println("Fetch completed");
                } catch (GitAPIException e) {
                    e.printStackTrace();
                }
            });

            executor.submit(() -> {
                try (Git git = new Git(repository)) {
                    Thread.sleep(1000); // Simulate delay
                    git.pull().call();
                    System.out.println("Pull completed");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            executor.shutdown();
            executor.awaitTermination(30, TimeUnit.SECONDS);
        }
    }

    private static Repository openRepository() throws IOException {
        // Implementation to open repository
        return null;
    }
}

Resource Cleanup During Retries

Ensure resources are properly cleaned up even when operations fail and are retried.

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;

public class ResourceCleanupDuringRetries {
    
    public static void fetchWithResourceCleanup(Repository repository) throws Exception {
        Exception lastException = null;
        
        for (int attempt = 1; attempt <= 3; attempt++) {
            // Create new Git instance for each attempt to ensure clean state
            try (Git git = new Git(repository)) {
                git.fetch().call();
                return; // Success
            } catch (GitAPIException | IOException e) {
                lastException = e;
                System.err.println("Attempt " + attempt + " failed: " + e.getMessage());
                
                if (attempt < 3) {
                    Thread.sleep(1000 * attempt); // Backoff
                }
            }
        }
        
        throw lastException;
    }
}

For more advanced patterns, see Error Handling in Patterns and Retry Pattern for Network Operations.

Next Steps

docs

remote

index.md

tile.json