Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine number of commit ahead and behind using JGit

Tags:

jgit

On a GitHub project, when we go to any branches page, we can see graphs which describes commit ahead/behind numbers of a branch w.r.t. master.

How can we determine those ahead behind numbers using JGit?

I used BranchTrackingStatus class for this, but I'm getting BranchTrackingStatus object always null.

Here is the code which I used

private static Lis<Integer> getCounts(Repository repository, String branchName) throws IOException{
  BranchTrackingStatus trackingStatus = BranchTrackingStatus.of(repository, branchName);
  List<Integer> counts = new ArrayList<Integer>();
  if (trackingStatus != null){
      counts.add(trackingStatus.getAheadCount());
      counts.add(trackingStatus.getBehindCount());
  } else {
      counts.add(0);
      counts.add(0);
  }
  return counts;
}

public void show(String repoName, String baseBranchName) throws IOException, GitAPIException{    

  Repository repository = repoManager.openRepository(new Project.NameKey(repoName));

  List<Ref> call = new Git(repository).branchList().call();
  for (Ref ref : call) {
    List<Integer> counts = getCounts(repository, ref.getName());
    System.out.println("Commits ahead : "+counts.get(0));
    System.out.println("Commits behind : "+counts.get(1));
  }
}
like image 598
Gaurav Chaudhary Avatar asked May 12 '14 09:05

Gaurav Chaudhary


2 Answers

BranchTrackingStatus.of() assumes that branchName denotes a local branch, either by its full name (e.g. refs/heads/master) or its short name (e.g. master). It returns null if the given branchName cannot be found or the tracking branch is not configured or does not exist.

To compare two arbitrary branches, you could adopt the BranchTrackingStatus code like so:

void calculateDivergence(Ref local, Ref tracking) throws IOException {
  try (RevWalk walk = new RevWalk(repository)) {
    RevCommit localCommit = walk.parseCommit(local.getObjectId());
    RevCommit trackingCommit = walk.parseCommit(tracking.getObjectId());
    walk.setRevFilter(RevFilter.MERGE_BASE);
    walk.markStart(localCommit);
    walk.markStart(trackingCommit);
    RevCommit mergeBase = walk.next();
    walk.reset();
    walk.setRevFilter(RevFilter.ALL);
    aheadCount = RevWalkUtils.count(walk, localCommit, mergeBase);
    behindCount = RevWalkUtils.count(walk, trackingCommit, mergeBase);
  }
}
like image 156
Rüdiger Herrmann Avatar answered Oct 25 '22 17:10

Rüdiger Herrmann


Your code looks fine to me, I took some of it and added it as a sample in the jgit-cookbook to see if it works. Locally I see counts when there are actual differences to the remote repostory.

Please note how BranchTrackingStatus works: It will not do a remote request and fetch the latest commits from the remote side, but it will only show what the local git repository has on the remote-tracking branches compared to the local branches.

I.e. you probably need to do a git fetch first on a repository that has updates on the remote side in order to get the status of the remote repository updated and only then BranchTrackingStatus will show values.

like image 26
centic Avatar answered Oct 25 '22 16:10

centic