Master Mind
Master Mind

Reputation: 3084

JGit: read the content of a file at a commit in a branch

I want to read the content of a file at a certain commit in a certain branch: I am currently, using this code to read the content of a file at a certain commit ignoring the branch.

    public static String readContentOfFileAtCommit(String commitStr, String fileName)
        throws IOException {

    String content = null;
    ObjectId lastCommitId = currentRepo.resolve(commitStr);

    try (RevWalk revWalk = new RevWalk(currentRepo)) {
        RevCommit commit = revWalk.parseCommit(lastCommitId);
        RevTree tree = commit.getTree();

        try (TreeWalk treeWalk = new TreeWalk(currentRepo)) {
            treeWalk.addTree(tree);
            treeWalk.setRecursive(true);
            treeWalk.setFilter(PathFilter.create(fileName));
            if (!treeWalk.next()) {
                throw new IllegalStateException("Did not find expected file:" + fileName);
            }

            ObjectId objectId = treeWalk.getObjectId(0);
            ObjectLoader loader = currentRepo.open(objectId);
            content = new String(loader.getBytes());
        }

        revWalk.dispose();
    }

    return content;
}

My goal is to get the content of a file at a certain commit that is done on a certain branch.

Upvotes: 5

Views: 3481

Answers (1)

Mincong Huang
Mincong Huang

Reputation: 5552

Different from most older VCS tools branch, a branch in Git is simply a lightweight movable pointer to one of these commits. It does not "contain" any commits itself. In other words, it's only a simple file that contains the 40 character SHA-1 checksum of the commit it points to. There's also a very illustrative example in Git - Branches in a Nutshell:

A branch and its commit history

As stated by Rüdiger Herrmann, while a commit is usually created on a branch, you cannot say that a commit "was done on a branch" after the fact. Branches may be added, deleted, renamed, or updated there after. For example, even if the branch or tag v1.0 is removed, the commit 98ca9, 34ac2, f30ab are still there, and reachable by master. I would suggest you to read the Pro Git (2nd Edition), Chapter 3.1 Git - Branches in a Nutshell for more detail.

As for JGit, here's my implementation of reading path for a specific commit:

private String getContent(RevCommit commit, String path) throws IOException {
  try (TreeWalk treeWalk = TreeWalk.forPath(git.getRepository(), path, commit.getTree())) {
    ObjectId blobId = treeWalk.getObjectId(0);
    try (ObjectReader objectReader = repo.newObjectReader()) {
      ObjectLoader objectLoader = objectReader.open(blobId);
      byte[] bytes = objectLoader.getBytes();
      return new String(bytes, StandardCharsets.UTF_8);
    }
  }
}

Upvotes: 9

Related Questions