使用JGit,我希望git log --full-history -p -1 <hash-id>
尽可能获得提交文件中的更改列表。
这可能吗?如果是这样,你怎么做?
我知道如何获得每次提交,并查看提交消息:
//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();
是什么让我可以获得文件中的更改?
例如我写道:
git log --full-history -p -1 8309c1262e1b7ffce8fc86efc1ae5777a4a96777
回复是
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);
我希望得到以下内容。变化是一个补课:
//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();
输出看起来像:
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
答案 0 :(得分:5)
JGit有一个非常简单的diff
命令,可以将两次提交之间的更改的文本差异写入输出流。
例如:
OutputStream outputStream = ...
List<DiffEntry> diffEntries = git.diff().setOutputStream( outputStream ).call();
调用命令后返回的DiffEntry
列表可能更有趣。
每个DiffEntry表示一个已更改的文件,并告知其路径名称,是否已添加,更改或删除,指向(blob-id&#39; s)旧内容和新内容等等。
从每个DiffEntry
,您可以获得EditList
,其中包含有关哪些行已更改的信息。
例如:
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();
}
此代码还说明了如何在不使用DiffCommand
的情况下获得具有更详细控制的差异条目。
就在最近,我写了一篇关于JGit差异API的完整博客文章。有关详细信息,请参阅此处:http://www.codeaffine.com/2016/06/16/jgit-diff/
答案 1 :(得分:4)
感谢Rüdiger Herrmann提供反馈,并感谢他gist上的部分代码。
我创建了一个方法diffCommit(String hashID)
,其中包含3个辅助函数,其工作方式与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);
}
}
}
以下是产生与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 );
}
}
}