2

Right now I am using git log:

try (Git git = new Git(repo)) {
    Iterable<RevCommit> commits = git.log().all().call();
    for (RevCommit commit : commits) {
        System.out.println("LogCommit: " + commit);
        TreeWalk treeWalk = new TreeWalk(repo);
        treeWalk.reset(commit.getTree().getId());
        while( treeWalk.next() ) {
            String filename = treeWalk.getPathString();
            Integer currentCount = 0;
            if(fileChanges.containsKey(filename)) {
                currentCount = fileChanges.get(filename);
            }
            fileChanges.put(filename, new Integer(currentCount + 1));  
        }
        treeWalk.close();
    }           
} 

The problem with this is it lists all of the files in the commit, whether or not they have been changed. Suppose I change a css file, commit the repo and then run this code, every other file in the entire repo will have the number of times changed incremented by one.

EDIT: I believe this snippet of code does it:

try (Git git = new Git(repo)) {

            DiffFormatter df = new DiffFormatter(NullOutputStream.INSTANCE);
            df.setRepository( git.getRepository() );

            Iterable<RevCommit> commits = git.log().all().call();
            for (RevCommit commit : commits) {
                if(commit.getParents().length != 0) {
                    System.out.println("LogCommit: " + commit);

                    List<DiffEntry> entries = df.scan(commit.getId(), commit.getParent(0).getId());
                    for( DiffEntry entry : entries ) {
                        String filename = entry.getPath(DiffEntry.Side.NEW);

                        if(!filename.equals("/dev/null")) {
                            Integer currentCount = 0;

                            if(fileChanges.containsKey(filename)) {
                                currentCount = fileChanges.get(filename);
                            }else {
                                System.out.println("    DiffEntry: " +entry.getPath(DiffEntry.Side.NEW));
                            }
                            fileChanges.put(filename, new Integer(currentCount + 1));
                        }
                    }
                }
            }
        }
davidahines
  • 3,976
  • 16
  • 53
  • 87
  • Not familliar with jgit. But if you try to do this then you will know the number of times the file has been commited (git log --follow filename ). See if this helps – karthick Jan 25 '18 at 18:51
  • Can you please elaborate a little bit more detailed on what you want to count? What about renames or deleted files? – TobiSH Jan 25 '18 at 18:58
  • I'd like to count the number of times a file has changed, for non-deleted files, if a file is renamed, I would like it to carry over the count to the new name. – davidahines Jan 25 '18 at 19:09
  • Hmm, this is indeed an interesting problem. A commit contains always a reference to a tree which contains the entire tree (the entire dir) with reference to a blobs. A plumber way to figure out which files where changed in a commit is: `git diff-tree --no-commit-id --name-only -r `. Maybe that gives you a hint on how to go on with jgit – TobiSH Jan 25 '18 at 19:29
  • 1
    Instead of comparing to `/dev/null` you could use `DiffEntry::getChangeType`. – Rüdiger Herrmann Jan 31 '18 at 06:47

1 Answers1

3

I think what you are looking for is the respective diffs of all commits. The following post should help to list all commits: How to write git log --stat command in JGit

To get the diff between two commits look here: How to show changes between commits with JGit

For a more in-depth discussion of JGit's diff APIs I wrote an article some while ago: http://www.codeaffine.com/2016/06/16/jgit-diff/

Rüdiger Herrmann
  • 20,512
  • 11
  • 62
  • 79