How to use jgit to programmatically manage git workflow like repository management, pull and push operations etc.
JGit developed by the Eclipse Foundation is a java implementation of the git workflow. When included as a maven or gradle dependency, it allows you to execute most of the git cli commands programmatically, removing the dependency triggering external commands from a java program.
As part of this post, we’ll explore the usage of JGit for some commonly used commands:
The init command is used by git to initialize a blank repository on a local system which can then be linked to a remote repository. A hidden .git directory is created inside the working directory which holds all the configuration files corresponding to the remote repository.
When using CLI, following commands are required to be executed:
sumit@jvmaware:~/jgit-demo$ git init
Initialized empty Git repository in /home/gaurs/jgit-demo/.git/
sumit@jvmaware:~/jgit-demo$ git config user.email "sumit@jvmaware.com"
sumit@jvmaware:~/jgit-demo$ git config user.name "jvmaware"
sumit@jvmaware:~/jgit-demo$ git remote add origin https://github.com/jvmaware/jgit-demo.git
Using JGit, we can achieve similar results by executing the following code:
try(Git git = Git.init().setDirectory(Paths.get("D:\\jgit-demo").toFile()).call()){
git.remoteAdd().setName("origin").setUri(new URIish("https://github.com/jvmaware/jgit-demo.git")).call();
}catch(GitAPIException | URISyntaxException exception){
log.error("exception occurred while initializing repository", exception);
}
For an existing remote repository, we can clone the same to our local environment and add changes to it afterwards. Following CLI command will create a copy of the remote repository in the same directory from where it is called:
sumit@jvmaware:~/jgit-demo$ git clone https://github.com/jvmaware/jgit-demo.git
Using JGit, the clone process looks something like:
private void cloneRepository(String localPath, String remotePath) {
try {
if (Files.notExists(Paths.get(localPath))) {
Files.createDirectories(Paths.get(localPath));
CloneCommand gitCommand = prepareCloneCommand(localPath, remotePath);
gitCommand.call();
}else{
log.info("[{}] dir exists; will skip the clone stage", localPath);
}
} catch (IOException | GitAPIException exception) {
log.error("exception occurred while cloning remote repo");
throw new RuntimeException(exception);
}
}
private CloneCommand prepareCloneCommand(String localPath, String remotePath) {
CloneCommand cloneCommand = Git.cloneRepository().setURI(remotePath).setDirectory(Paths.get(localPath).toFile());
UsernamePasswordCredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("username", "password");
cloneCommand.setCredentialsProvider(credentialsProvider);
return cloneCommand;
}
The git pull command is used to fetch changes from a remote repository and immediately update our local repository with those. This includes merging any non-conflicting changes. The general syntax for the pull command is :
sumit@jvmaware:~/jgit-demo$ git pull
Using JGit, we prepare a pull command which is then used to update a local repository - denoted by source
(connected to a remote repository) with the changes:
private void pullChanges() {
try (Git git = Git.open(Paths.get(source).toFile())) {
PullCommand pull = preparePullCommand(git);
pull.call();
} catch (IOException | GitAPIException exception) {
log.error("exception occurred while pulling changes from remote repo");
throw new RuntimeException(exception);
}
}
private PullCommand preparePullCommand(Git git) {
PullCommand pull = git.pull();
UsernamePasswordCredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("<useName>", "<passWord>");
pull.setCredentialsProvider(credentialsProvider);
return pull;
}
Similar to the pull command mentioned above, we can create a push command instance that is used to publish our changes to the remote repository. When preparing a push command, a few additional steps are required:
destination
denotes the dir containing changes to be published.addFilepattern
method.UsernamePasswordCredentialsProvider
.remote
and RefSpecs
:private void pushChanges() {
try (Git git = Git.open(Paths.get(destination).toFile())) {
git.add().addFilepattern(".").call();
git.commit().setMessage( "updated for changes on: " + LocalDate.now()).call();
preparePushCommand(git).setRemote("origin").setRefSpecs(new RefSpec("refs/heads/main:refs/heads/main")).call();
} catch (IOException | GitAPIException exception) {
log.error("exception occurred while pulling changes from remote repo");
throw new RuntimeException(exception);
}
}
private PushCommand preparePushCommand(Git git) {
PushCommand push = git.push();
UsernamePasswordCredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("<useName>", "<passWord>");
push.setCredentialsProvider(credentialsProvider);
return push;
}
Be notified of new posts. Subscribe to the RSS feed.