Eclipse JGit Documentation

repository·master·Indexed 19 days ago

https://github.com/eclipse-jgit/jgit

A pure Java implementation of the Git version control system that allows Java applications to perform operations like cloning, fetching, and pushing without a native Git installation. Documentation covers core library usage, module overviews (including LFS, HTTP, and CLI support), and detailed SSH configuration for Apache MINA sshd and JSch, including SSH agent transports for Windows, Linux, OS X, and BSD, as well as PKCS#11 HSM support.

Tokens
10.8K
Snippets
21
Records
49
Agent score
65%

What's inside Eclipse JGit

  1. Overview of Eclipse JGit

    master
    Eclipse JGit is a pure Java implementation of the Git version control system. It allows developers to read and write Git repositories and operate on working directories directly within Java applications without requiring a native Git installation.
  2. Use JGit SSH support via JSch

    master

    This bundle provides an implementation of git transport over SSH using the JSch library.

    Warning: This bundle is deprecated and essentially unmaintained. The JGit project may remove it at any time. For officially supported SSH transport, use the org.eclipse.jgit.ssh.apache bundle, which is built upon Apache MINA sshd.

  3. What is the reftable format?

    master

    The reftable format is a portable binary file format designed for efficient Git reference storage. It is intended as a high-performance alternative to the traditional packed-refs format and loose reference files.

    Key characteristics include:

    • Efficient Lookups: Supports near constant-time lookup for single references, SHA-1 verification, and namespace scans (e.g., refs/tags/).
    • Optimized Storage: Uses variable-sized blocks with prefix compression to reduce disk space. It also allows combining reflog storage with ref storage for small transactions.
    • Scalability: Designed to handle repositories with massive numbers of references (e.g., hundreds of thousands) without the linear scan penalties of packed-refs or the inode exhaustion issues of loose references.
    • Atomic Operations: Supports atomic pushes with $O(\text{size of update})$ complexity, avoiding the need to rewrite the entire file for small changes.
  4. SSH Agent support and limitations

    master

    JGit supports communication with SSH agents using the OpenSSH protocol (the newer SSH2 protocol). It does not support the older SSH1 protocol.

    Agent Discovery

    JGit discovers agent connectors via the ServiceLoader mechanism using the SPI org.eclipse.jgit.transport.sshd.agent.ConnectorFactory. If no implementation is found, JGit will not attempt to use an SSH agent.

    SSH Config for Agents

    When using ~/.ssh/config, the following properties are supported:

    • AddKeysToAgent: Can be no, yes, ask, confirm, or include key lifetimes. Note that on Windows, Pageant and Win32-OpenSSH do not support confirm or lifetime constraints.
    • IdentityAgent: Specifies which agent to use, or none to disable agent use.
    • IdentitiesOnly: If set to yes, only keys listed in an IdentityFile (and having a corresponding *.pub file) are considered. This prevents JGit from trying default key names like ~/.ssh/id_rsa.
  5. Configure Reftable block size and alignment

    master

    When implementing or reading reftables, consider the following regarding block management:

    • Block Size: Determined by the writer. It must be larger than the longest reference name or log entry. Recommended sizes are powers of two (e.g., 4k, 8k) for filesystem friendliness. Larger sizes (64k) improve compression but increase access costs. The maximum allowed block size is 16777215 bytes (15.99 MiB).
    • Alignment: Writers can align blocks at multiples of the block size using padding (NUL bytes).
      • If aligned: The block_size field in the header must specify the alignment.
      • If unaligned: The header must set block_size = 0 and omit padding. Unaligned files with multiple ref blocks must include a ref_index to support fast lookups.
    • First Block Exception: The first ref block shares the same block as the file header and is 24 bytes smaller than subsequent blocks.
  6. Understand the Reftable file structure

    master

    A reftable file is a structured binary format used for storing Git references and logs. The high-level structure consists of a header, followed by various data blocks (references, objects, logs) and their corresponding indices, ending with a footer.

    Standard Reftable Structure:

    1. first_block (contains the file header and the first reference block)
    2. ref_block* (zero or more reference blocks)
    3. ref_index* (zero or more reference index blocks)
    4. obj_block* (optional object blocks)
    5. obj_index* (optional object index blocks)
    6. log_block* (zero or more log blocks)
    7. log_index* (zero or more log index blocks)
    8. footer (contains metadata and pointers to index positions)

    Log-only Reftable Structure: If the file only contains logs, it omits reference and object sections:

    1. first_block (contains the file header)
    2. log_block*
    3. log_index*
    4. footer

    In log-only files, the first log block immediately follows the header without padding.

    first_block {
      header
      first_ref_block
    }
    ref_block*
    ref_index*
    obj_block*
    obj_index*
    log_block*
    log_index*
    footer
  7. Understand Log Block and Log Record formats

    master

    Log blocks (block_type = 'g') are always unaligned and variable in size. They use zlib deflate compression.

    Log Block Structure:

    1. uint24( block_len ): The inflated size (including the 4-byte header). Use this to preallocate the inflation buffer.
    2. zlib_deflate payload containing:
      • log_record+
      • uint24( restart_offset )+
      • uint16( restart_count )

    Log Record Format: Log records use a key structured as: ref_name '\0' reverse_int64( update_index ). The reverse_int64 ensures that higher update_index values (more recent) sort first.

    Log Record Fields:

    • log_type: 0x0 (deletion) or 0x1 (standard git reflog data).
    • For log_type = 0x1, the log_data includes:
      • old_id (20-byte SHA-1)
      • new_id (20-byte SHA-1)
      • name (committer name)
      • email (committer email)
      • time_seconds (seconds since epoch)
      • tz_offset (signed minutes from GMT)
      • message (reflog message)
  8. Explore JGit Modules

    master

    JGit is organized into several modules depending on your requirements:

    • org.eclipse.jgit: The core pure Java library for reading/writing repositories and working directories. It has no additional support library dependencies.
    • org.eclipse.jgit.ant: Provides Ant tasks based on JGit.
    • org.eclipse.jgit.archive: Supports exporting to various archive formats (e.g., zip).
    • org.eclipse.jgit.http.apache: Provides Apache HttpClient support.
    • org.eclipse.jgit.http.server: A server implementation for the smart and dumb Git HTTP protocol.
    • org.eclipse.jgit.lfs: Support for Git Large File Storage (LFS).
    • org.eclipse.jgit.lfs.server: Basic LFS server support.
    • org.eclipse.jgit.pgm: A command-line interface (CLI) implementing Git commands using JGit.
    • org.eclipse.jgit.ssh.apache: SSH protocol client support based on Apache Mina sshd.
    • org.eclipse.jgit.ssh.apache.agent: Optional SSH agent support for the Apache SSH client.
    • org.eclipse.jgit.ui: A simple UI for displaying the git log.
  9. How JGit discovers SSH implementations

    master

    JGit uses the java.util.ServiceLoader to find implementations of the org.eclipse.jgit.transport.ssh.SshSessionFactory interface.

    • Automatic Discovery: If the service declaration is on the Classpath of the org.eclipse.jgit bundle, JGit will automatically pick it up.
    • Selection Logic: JGit simply uses the first SshSessionFactory provided by the ServiceLoader.
    • OSGi Environments: In OSGi, you may need a service loader bridge or an OSGi fragment for the org.eclipse.jgit bundle to ensure the service declaration is visible on its Classpath.
    • Manual Override: If discovery fails, you can manually set the factory using SshSessionFactory.setInstance() (globally) or via a TransportConfigCallback (per command).
  10. Implement binary search within a block using restart_offsets

    master

    To avoid linear scans of entire blocks, reftables use a restart_offset table located at the end of blocks (ref, obj, or index blocks).

    How it works:

    1. A block contains a restart_count (uint16) and a list of restart_offset values (uint24).
    2. Each restart_offset is relative to the start of the block and points to the first byte of a ref_record whose name has not been prefix compressed (i.e., its prefix_length is 0).
    3. Search Process:
      • Binary search the restart_offset list to find the two restart points between which the target key resides.
      • Perform a linear scan starting from the identified restart point.
      • Terminate the scan once a record is found that sorts after the target key.

    Writer Recommendation: Use a restart interval of 16 for small blocks (4k/8k) and 64 for larger blocks (64k).

  11. Understand the reftable repository layout

    master

    Reftable files are stored in the $GIT_DIR/reftable/ directory. The repository uses a stack of files to manage references and logs.

    File Types

    • .log files: Contain only log entries.
    • .ref files: Contain either only references or a mix of references and logs.

    The Stack (tables.list)

    The file $GIT_DIR/reftable/tables.list maintains the order of the stack, from oldest (base) to newest (most recent).

    Important for Readers: To get the current state of references, readers must read tables.list and search through the files in reverse order (examining the last file in the list first).

    # Example of the stack order
    $ cat .git/reftable/tables.list
    00000001-00000001.log
    00000002-00000002.ref
    00000003-00000003.ref