使用JGit获得某一次Commit修改的文件列表的方法

这篇博客的目的如标题所示。JGit是大家常用的分析Repository Git相关数据的工具,这个需求按道理来说很简单。JGit最新版的文档链接是:https://download.eclipse.org/jgit/site/5.3.0.201903130848-r/apidocs/index.html。

我找了一些相关的代码和StackOverflow的讨论,主要参考了下面两个链接:

https://github.com/centic9/jgit-cookbook/blob/master/src/main/java/org/dstadler/jgit/porcelain/ShowChangedFilesBetweenCommits.java

https://stackoverflow.com/questions/39935160/how-to-use-jgit-to-get-list-of-changes-in-files

下面贴出我写的代码,很简单,也没怎么注意代码效率之类的:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;

public class Debug {
	
	static List getChangedFileList(RevCommit revCommit, Repository repo) {
		List returnDiffs = null;
		try {
			RevCommit previsouCommit=getPrevHash(revCommit,repo);
			if(previsouCommit==null)
				return null;
			ObjectId head=revCommit.getTree().getId();
			
			ObjectId oldHead=previsouCommit.getTree().getId();
			
			System.out.println("Printing diff between the Revisions: " + revCommit.getName() + " and " + previsouCommit.getName());

            // prepare the two iterators to compute the diff between
    		try (ObjectReader reader = repo.newObjectReader()) {
        		CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
        		oldTreeIter.reset(reader, oldHead);
        		CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
        		newTreeIter.reset(reader, head);

        		// finally get the list of changed files
        		try (Git git = new Git(repo)) {
                    List diffs= git.diff()
            		                    .setNewTree(newTreeIter)
            		                    .setOldTree(oldTreeIter)
            		                    .call();
                    for (DiffEntry entry : diffs) {
//                        System.out.println("Entry: " + entry);
                    }
                    returnDiffs=diffs;
        		} catch (GitAPIException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
    		}			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnDiffs;
	}
	
	public static RevCommit getPrevHash(RevCommit commit, Repository repo)  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;
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String versionCommit="ecf89a60bfd8089d1b1de5666bd2e9d5938abe8e";//需要分析的Commit Hash		
		String path="D:\\Projects\\Subject-Versions\\activemq";//对应项目在本地Repo的路径
		FileRepositoryBuilder builder = new FileRepositoryBuilder();
		builder.setMustExist(true);
		builder.addCeilingDirectory(new File(path));
		builder.findGitDir(new File(path));
		
		Repository repo;
		try {
			repo = builder.build();
			RevWalk walk = new RevWalk(repo);
			ObjectId versionId=repo.resolve(versionCommit);
			RevCommit verCommit=walk.parseCommit(versionId);
			List diffFix=getChangedFileList(verCommit,repo);
			for (DiffEntry entry : diffFix) {
				System.out.println(entry.getNewPath());
            }
//			RevWalk walk2 = new RevWalk(repo);
//			ObjectId versionId2=repo.resolve(versionCommit);
//			RevCommit verCommit2=walk2.parseCommit(versionId2);
//			List diffFix2=RunJGit.getChangedFileList(verCommit2,repo);
//			for (DiffEntry entry : diffFix2) {
//				System.out.println(entry.getNewPath());
//            }	
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

具体大家结合注释看看就明白,需要强调的是我在最下面注释掉的一部分代码,我在调试过程中发现,如果第二次再调用同样的方法,就不能正确获取到列表了,解决方案是重新定义一个RevWalk对象,由于我对JGit不熟悉,实在不知道为什么要这样做,只是简单总结一下。

你可能感兴趣的:(使用JGit获得某一次Commit修改的文件列表的方法)