How to use JGit to get a list of file changes?

Using JGit, I want to get a list of changes to commit files, as possible with git log --full-history -p -1 <hash-id> .

Is it possible? If so, how do you do it?

I know how to get each commit and see the commit message:

 //Load repo FileRepositoryBuilder builder = new FileRepositoryBuilder(); Repository repo = builder.setGitDir(new File("/path/to/repo/.git")).setMustExist(true).build(); Git git = new Git(repo); //get commits Iterable<RevCommit> log = git.log().call(); for (RevCommit commit : log) { //Shows the hashid System.out.println("LogCommit: " + commit); //Shows only commit message String logMessage = commit.getFullMessage(); System.out.println("LogMessage: " + logMessage); } git.close(); 

What allows me to get changes in files?

For example, I write:

 git log --full-history -p -1 8309c1262e1b7ffce8fc86efc1ae5777a4a96777 

Answer

 commit 8309c1262e1b7ffce8fc86efc1ae5777a4a96777 Author: <redacted> Date: Thu Aug 4 12:15:23 2016 -0400 Fixed typo in commit diff --git a/Product/Production/Common/CONNECTCoreLib/src/main/java/gov/hhs/fha/nhinc/messaging/server/BaseService.java b/Product/Production/Common/CONNECTCoreLib/src/main/java/gov/hhs/fha/nhinc/messaging/server/BaseService.java index fa55e7e..4f3c155 100644 --- a/Product/Production/Common/CONNECTCoreLib/src/main/java/gov/hhs/fha/nhinc/messaging/server/BaseService.java +++ b/Product/Production/Common/CONNECTCoreLib/src/main/java/gov/hhs/fha/nhinc/messaging/server/BaseService.java @@ -56,6 +57,7 @@ public abstract class BaseService { protected AssertionType getAssertion(WebServiceContext context, AssertionType assertionIn) { AssertionType assertion; - WSAHeaderHelper wsaHlpr = new WSAHeaderHelper(); + WSAHeaderHelper wsaHelper = new WSAHeaderHelper(); if (assertionIn == null) { assertion = SAML2AssertionExtractor.getInstance().extractSamlAssertion(context); 

I want to have something like the following. Change is a class:

 //Load repo FileRepositoryBuilder builder = new FileRepositoryBuilder(); Repository repo = builder.setGitDir(new File("/path/to/repo/.git")).setMustExist(true).build(); Git git = new Git(repo); //get commits Iterable<RevCommit> log = git.log().call(); for (RevCommit commit : log) { //Shows the hashid System.out.println("LogCommit: " + commit); //Shows only commit message String logMessage = commit.getFullMessage(); System.out.println("LogMessage: " + logMessage); List<Change> changes = commit.getChanges(); for(Change change: changes): System.out.println("File: " + change.getFile()); System.out.println("Change: " + change.getChange()); System.out.println("ChangeType: " + change.getChangeType()); } git.close(); 

The result will look something like this:

 LogCommit: 8309c1262e1b7ffce8fc86efc1ae5777a4a96777 LogMessage: Fixed typo in commit File: Product/Production/Common/CONNECTCoreLib/src/main/java/gov/hhs/fha/nhinc/messaging/server/BaseService.java Change: WSAHeaderHelper wsaHlpr = new WSAHeaderHelper(); ChangeType: D File: Product/Production/Common/CONNECTCoreLib/src/main/java/gov/hhs/fha/nhinc/messaging/server/BaseService.java Change: WSAHeaderHelper wsaHelper = new WSAHeaderHelper(); ChangeType: A 
+10
source share
2 answers

Thanks to Rüdiger Herrmann for the tip and part of the code found on his list .

I created a diffCommit(String hashID) method with 3 helper functions that will work just like git log --full-history -p -1 <hash-id>.

 private Git git; private Repository repo; private void diffCommit(String hashID) throws IOException { //Initialize repositories. FileRepositoryBuilder builder = new FileRepositoryBuilder(); repo = builder.setGitDir(new File("/path/to/repo" + "/.git")).setMustExist(true) .build(); git = new Git(repo); //Get the commit you are looking for. RevCommit newCommit; try (RevWalk walk = new RevWalk(repo)) { newCommit = walk.parseCommit(repo.resolve(hashID)); } System.out.println("LogCommit: " + newCommit); String logMessage = newCommit.getFullMessage(); System.out.println("LogMessage: " + logMessage); //Print diff of the commit with the previous one. System.out.println(getDiffOfCommit(newCommit)); } //Helper gets the diff as a string. private String getDiffOfCommit(RevCommit newCommit) throws IOException { //Get commit that is previous to the current one. RevCommit oldCommit = getPrevHash(newCommit); if(oldCommit == null){ return "Start of repo"; } //Use treeIterator to diff. AbstractTreeIterator oldTreeIterator = getCanonicalTreeParser(oldCommit); AbstractTreeIterator newTreeIterator = getCanonicalTreeParser(newCommit); OutputStream outputStream = new ByteArrayOutputStream(); try (DiffFormatter formatter = new DiffFormatter(outputStream)) { formatter.setRepository(git.getRepository()); formatter.format(oldTreeIterator, newTreeIterator); } String diff = outputStream.toString(); return diff; } //Helper function to get the previous commit. public RevCommit getPrevHash(RevCommit commit) throws IOException { try (RevWalk walk = new RevWalk(repo)) { // Starting point walk.markStart(commit); int count = 0; for (RevCommit rev : walk) { // got the previous commit. if (count == 1) { return rev; } count++; } walk.dispose(); } //Reached end and no previous commits. return null; } //Helper function to get the tree of the changes in a commit. Written by Rüdiger Herrmann private AbstractTreeIterator getCanonicalTreeParser(ObjectId commitId) throws IOException { try (RevWalk walk = new RevWalk(git.getRepository())) { RevCommit commit = walk.parseCommit(commitId); ObjectId treeId = commit.getTree().getId(); try (ObjectReader reader = git.getRepository().newObjectReader()) { return new CanonicalTreeParser(null, reader, treeId); } } } 

Here is additional code that will produce output similar to git log --full-history

 public void commit_logs() throws IOException, NoHeadException, GitAPIException { List<String> logMessages = new ArrayList<String>(); FileRepositoryBuilder builder = new FileRepositoryBuilder(); Repository repo = builder.setGitDir(new File("/path/to/repo" + "/.git")) .setMustExist(true).build(); git = new Git(repo); Iterable<RevCommit> log = git.log().call(); RevCommit previousCommit = null; for (RevCommit commit : log) { if (previousCommit != null) { AbstractTreeIterator oldTreeIterator = getCanonicalTreeParser( previousCommit ); AbstractTreeIterator newTreeIterator = getCanonicalTreeParser( commit ); OutputStream outputStream = new ByteArrayOutputStream(); try( DiffFormatter formatter = new DiffFormatter( outputStream ) ) { formatter.setRepository( git.getRepository() ); formatter.format( oldTreeIterator, newTreeIterator ); } String diff = outputStream.toString(); System.out.println(diff); } System.out.println("LogCommit: " + commit); String logMessage = commit.getFullMessage(); System.out.println("LogMessage: " + logMessage); logMessages.add(logMessage.trim()); previousCommit = commit; } git.close(); } private AbstractTreeIterator getCanonicalTreeParser( ObjectId commitId ) throws IOException { try( RevWalk walk = new RevWalk( git.getRepository() ) ) { RevCommit commit = walk.parseCommit( commitId ); ObjectId treeId = commit.getTree().getId(); try( ObjectReader reader = git.getRepository().newObjectReader() ) { return new CanonicalTreeParser( null, reader, treeId ); } } } 
+6
source

JGit has a very simple diff that writes a text report of changes between two commits to the output stream.

For instance:

 OutputStream outputStream = ... List<DiffEntry> diffEntries = git.diff().setOutputStream(outputStream).call(); 

Probably more interesting is the DiffEntry list returned after calling the command. Each DiffEntry represents a modified file and tells its path whether it has been added, changed or deleted, pointers (identifiers of blob-identifiers) to old and new content, and much more.

And from each DiffEntry you can get an EditList that contains information about which rows have been changed.

For instance:

 try (DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE)) { diffFormatter.setRepository(git.getRepository()); List<DiffEntry> diffEntries = diffFormatter.scan(oldTreeIterator, newTreeIterator); FileHeader fileHeader = diffFormatter.toFileHeader(diffEntries.get(0)); return fileHeader.toEditList(); } 

This code also shows how to get diff records with more granular control without using DiffCommand .

Most recently, I wrote a blog post about the JGit diff APIs. For more information, see here: http://www.codeaffine.com/2016/06/16/jgit-diff/

+7
source

Source: https://habr.com/ru/post/1257898/


All Articles