How to “cat” a file in JGit?

A while back I was looking for an embeddable distributed version control system in Java,
and I think I have found it in JGit, which is a pure Java implementation of git.
However, there is not much in the way of sample code or tutorials.

How can I use JGit to retrieve the HEAD version of a certain file (just like svn cat or hg cat whould do)?

  • A Git Source Control strategy for a live Sitecore website
  • Is it possible to slim a .git repository without rewriting history?
  • deploying a website/webapp via git/gitolite permissions error
  • For “git diff” is there a -U<infinity> option to show the whole file?
  • Composer & composer.lock in GIT and merge conflicts
  • Is a bidrectional Git<->Svn Sync (both writable) possible?
  • I suppose this involves some rev-tree-walking and am looking for a code sample.

  • Which commit hash to undo a pushed merge using git-revert?
  • How do I make a releases, builds, and/or snapshots with BitBucket?
  • Pycharm and bitbucket plugin
  • Unsupported Git version
  • What can cause git to mess with character encoding?
  • “git clean -f” doesn't leave an empty directory
  • 6 Solutions collect form web for “How to “cat” a file in JGit?”

    Unfortunately Thilo’s answer does not work with the latest JGit API. Here is the solution I found:

    File repoDir = new File("test-git");
    // open the repository
    Repository repository = new Repository(repoDir);
    // find the HEAD
    ObjectId lastCommitId = repository.resolve(Constants.HEAD);
    // now we have to get the commit
    RevWalk revWalk = new RevWalk(repository);
    RevCommit commit = revWalk.parseCommit(lastCommitId);
    // and using commit's tree find the path
    RevTree tree = commit.getTree();
    TreeWalk treeWalk = new TreeWalk(repository);
    treeWalk.addTree(tree);
    treeWalk.setRecursive(true);
    treeWalk.setFilter(PathFilter.create(path));
    if (!treeWalk.next()) {
      return null;
    }
    ObjectId objectId = treeWalk.getObjectId(0);
    ObjectLoader loader = repository.open(objectId);
    
    // and then one can use either
    InputStream in = loader.openStream()
    // or
    loader.copyTo(out)
    

    I wish it was simpler.

    Here’s a simpler version of @morisil’s answer, using some of the concepts from @directed laugh’s and tested with JGit 2.2.0:

    private String fetchBlob(String revSpec, String path) throws MissingObjectException, IncorrectObjectTypeException,
            IOException {
    
        // Resolve the revision specification
        final ObjectId id = this.repo.resolve(revSpec);
    
        // Makes it simpler to release the allocated resources in one go
        ObjectReader reader = this.repo.newObjectReader();
    
        try {
            // Get the commit object for that revision
            RevWalk walk = new RevWalk(reader);
            RevCommit commit = walk.parseCommit(id);
    
            // Get the revision's file tree
            RevTree tree = commit.getTree();
            // .. and narrow it down to the single file's path
            TreeWalk treewalk = TreeWalk.forPath(reader, path, tree);
    
            if (treewalk != null) {
                // use the blob id to read the file's data
                byte[] data = reader.open(treewalk.getObjectId(0)).getBytes();
                return new String(data, "utf-8");
            } else {
                return "";
            }
        } finally {
            reader.release();
        }
    }
    

    repo is a Repository object as created in the other answers.

    I followed @Thilo’s and @morisil’s answer to get this, compatible with JGit 1.2.0:

    File repoDir = new File("test-git/.git");
    // open the repository
    Repository repo = new Repository(repoDir);
    // find the HEAD
    Commit head = repo.mapCommit(Constants.HEAD);
    // retrieve the tree in HEAD
    Tree tree = head.getTree();
    
    // 1.2.0 api version here
    // find a file (as a TreeEntry, which contains the blob object id)
    TreeWalk treewalk = TreeWalk.forPath(repo, "b/test.txt", tree);
    // use the blob id to read the file's data
    byte[] data = repo.open(treewalk.getObjectId(0)).getBytes();
    

    I didn’t test the Java version but it should work. It translates from

    (.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))
    

    in clojure (following the same setup as the top section), which does work.

    Figured it out by myself. The API is quite low-level, but it’s not too bad:

    File repoDir = new File("test-git/.git");
    // open the repository
    Repository repo = new Repository(repoDir);
    // find the HEAD
    Commit head = repo.mapCommit(Constants.HEAD);
    // retrieve the tree in HEAD
    Tree tree = head.getTree();
    // find a file (as a TreeEntry, which contains the blob object id)
    TreeEntry entry = tree.findBlobMember("b/test.txt");
    // use the blob id to read the file's data
    byte[] data = repo.openBlob(entry.getId()).getBytes();
    

    I have started writing a library called gitective that contains many helpers for working with blobs, commits, and trees using JGit and is MIT-licensed and available on GitHub.

    Get content of file in HEAD commit

    Repository repo = new FileRepository("/repos/project/.git");
    String content = BlobUtils.getHeadContent(repo, "src/Buffer.java");
    

    Get content of a file on a branch

    Repository repo = new FileRepository("/repos/project/.git");
    String content = BlobUtils.getContent(repo, "master", "src/Buffer.java");
    

    Diff two files

    Repository repo = new FileRepository("/repos/project/.git");
    ObjectId current = BlobUtils.getId(repo, "master", "Main.java");
    ObjectId previous = BlobUtils.getId(repo, "master~1", "Main.java");
    Collection<Edit> edit = BlobUtils.diff(repo, previous, current);
    

    More examples of utilities provided are detailed in the README.

    There is some info at JGit Tutorial (but that also is neither really helpful nor complete and probably outdated since they switched to eclipse where no documentation is available yet).

    Git Baby is a git and github fan, let's start git clone.