A Git repository is represented in JGit through the Repository class that can be viewed as a handle to a repository. With a Repository instance, you can create JGit commands (through the Git factory class), gain access to configuration settings, resolve refs, etc.

There are several ways to obtain a repository reference, and because I have seen people having trouble here and there, this article summarizes how to access a Git repository with JGit.

Of Repositories and Builders

The class Repository is abstract to allow for implementations with different storage backends. For example, there is an InMemoryRepository for tests and experiments. But of course, most commonly used is the FileRepository, that represents a repository in the local filesystem. Because the actual implementations are considered internal, each Repository implementation has a corresponding repository builder that should be used to create instances thereof.

Hence the FileRepositoryBuilder is the recommended way to create a FileRepository. For historical reasons, there is also a RepositoryBuilder that does the same but will be removed with the next major version update.

Once you have configured a repository builder to your needs, call its build() method to have a repository created.

FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder(); repositoryBuilder.setMustExist( true ); repositoryBuilder.setGitDir( ... ); Repository repository = repositoryBuilder.build();

For layout reasons, I have put the method calls on a line each, but the FileRepositoryBuilder also implements a fluent interface so that method calls can be chained.



All methods discussed here apply to local repositories only. Git is a distributed version control system and as such is not designed to manipulate a remote repository directly.

To manipulate a remote repository, you have to clone it first. Now you can make modifications to the local copy, like commit new or changed files, create branches or tags, etc. To synchronize your changes with the remote repository, you will first have to integrate (aka fetch) changes (if any) from the remote and then finally push your local changes.

All methods discussed here apply to local repositories only. Git is a distributed version control system and as such is not designed to manipulate a remote repository directly.To manipulate a remote repository, you have to clone it first. Now you can make modifications to the local copy, like commit new or changed files, create branches or tags, etc. To synchronize your changes with the remote repository, you will first have to integrate (aka fetch) changes (if any) from the remote and then finally push your local changes.

Prefer setGitDir()

In JGit, a file-based repository is identified through a directory. However, two directories may appear suitable to identify a repository: The work directory wherein the currently checked out revision resides and the git directory which holds the object database and metadata (e.g. branches, tags, etc.).

While FileRepositoryBuilder has a setGitDir() as well as a setWorkTree() method, I recommend to always use setGitDir(), because

By default, the git directory is a direct subdirectory of the work directory, but this can be overridden through an environment variable or a configuration setting.

And then there are bare repositories that don’t have a work directory at all.

Is This a Repository?

The FileRepositoryBuilder’s build() method returns a Repository whether or not a repository exists. Even if the given directory does not exist, an instance is returned.

I found two ways to test if a given directory actually points to an existing repository. By calling setMustExist(true), the FileRepositoryBuilder can be configured only to build existing repositories.

Once the must-exist flag is turned on, build() will throw a RepositoryNotFoundException if no repository could be found. As a side note, this behavior is undocumented. It might be just a lapse in the JavaDoc, and I doubt that this behavior will change, but still there is no guarantee as if it was part of the API.

Alternatively, you can test if the returned repository’s object database actually exists.

Repository repository = repositoryBuilder.build(); if( repository.getObjectDatabase().exists() ) { ... }

As the name implies, ObjectDatabase.exists() returns true if there is an object database and false otherwise.

[EDIT 2014-11-12]

Unfortunately, the ObjectDatabase.exists() test has a flaw. Because Git creates the object database lazily, an empty, just initialized repository does not have an object database. Only after the first commit was done, the object database exists. Therefore, the test will return false for an empty repository even though it is a perfectly valid repository. What has proven a better approach so far is to test if the HEAD reference exists:

Repository repository = repositoryBuilder.build(); if( repository.getRef( "HEAD" ) != null ) { ... }

Even an empty repository has a HEAD and getRef() returns only null if there is actually no repository.

[END EDIT]

A Small Detour: findGitDir()

The repository builder also offers a findGitDir() method that can be used to search for a repository starting from a given directory and going its parent hierarchy upwards.

FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder(); repositoryBuilder.addCeilingDirectory( new F‌ile( "/home/user" ) ); repositoryBuilder.findGitDir( new F‌ile( "/home/user/git/foo/bar" ) );

The search ends if either a repository directory was found or the root of the file system was reached.

getGitDir() can be used to obtain the search result and returns the found git directory or null if none was found.

The search can be limited by adding one or more ceiling directories. If one of them is reached while walking up the directory hierarchy, the search ends.

Alternative: Git.open()

If you find the FileRepositoryBuilder inconvenient to use, there is also a shorthand: Git.open().

Git git = Git.open( new F‌ile( "/path/to/repo/.git" ) );

The method expects a File parameter that denotes the directory in which the repository is located. The directory can either point to the work directory or the git directory. Again, I recommend to use the git directory here.

If the given directory does not exist or does not contain a repository, a RepositoryNotFoundException will be thrown. On success, an instance of class Git is returned that can be used to access the repository (git.getRepository()) and create git commands.

Another Detour: Submodules

Submodules allow putting a clone of another repository as a subdirectory within the socalled parent repository. Because a submodule is a repository in its own, it is also represented through a Repository instance in JGit.

Obtaining a reference to a submodule works just fine with the API outlined above:

F‌ile moduleDir = new F‌ile( parentRepo.getWorkTree(), "modules/foo/.git" ); repositoryBuilder.setGitDir( moduleDir ); Repository submoduleRepo = repositoryBuilder.build();

The git directory of the submodule is composed of the work directory of the parent repository plus the relative path to the the submodule’s git directory.

But the class SubmoduleWalk also offers static convenience methods:

Repository submoduleRepo = SubmoduleWalk.getSubmoduleRepository( parentRepo, "modules/foo" ); // or Repository submoduleRepo = SubmoduleWalk.getSubmoduleRepository( new F‌ile( "/path/to/parent/repo" ), "modules/foo" );

The first parameter denotes the parent repository – either through the given Repository or through its work directory location – and the second parameter specifies the name of the submodule.

More than One Way to Access a Git Repository with JGit

While Git.open() is nice and short, the FileRepositoryBuilder gives you more control and a reliable way to determine if the repository exists. Whether you prefer the first or the latter probably depends on your use case. Just remember not to use the FileRepository constructor directly as is may vanish or changes its behavior without prior notice.

If you like to try out the examples listed here for yourself, I recommend to setup JGit with access to its sources and JavaDoc so that you have meaningful context information, content assist, debug-sources, etc.



If you are wondering what to do next with a repository, you may want to read

If you are wondering what to do next with a repository, you may want to read Getting Started with JGit . The tutorial explains the most commonly used Git commands and their respective JGit counterparts. It walks through the steps to create a repository, fetch contents from a remote, add and remove files to/from the history, inspect the history, and finally push back the changes to the originating repository.

I hope this article helped to clarify how to access a repository with JGit. If you have further questions, please let me know in the comments