如何在JGit中“捕捉”文件?

前段时间我正在寻找一个Java嵌入式分布式版本控制系统 ,我想我已经在JGit中找到了它,它是git的纯Java实现。 但是,示例代码或教程的方式并不多。

如何使用JGit检索某个文件的HEAD版本(就像svn cathg cat那样)?

我想这涉及一些转树行走,我正在寻找代码示例。

不幸的是,Thilo的答案不适用于最新的JGit API。 这是我找到的解决方案:

 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) 

我希望它更简单。

这是@ morisil回答的简单版本,使用@directed笑的一些概念并使用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是在其他答案中创建的Repository对象。

我跟着@ Thilo和@ morisil的回答得到了这个,与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(); 

我没有测试Java版本,但它应该工作。 它翻译自

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

在clojure中(遵循与顶部相同的设置),这确实有效。

自己弄清楚了。 API非常低级,但它并不太糟糕:

 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(); 

我已经开始编写一个名为gitective的库,其中包含许多帮助程序,用于使用JGit处理blob,提交和树,并且是MIT许可的,可以在GitHub上使用。

在HEAD提交中获取文件内容

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

获取分支上的文件内容

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

差异两个文件

 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 = BlobUtils.diff(repo, previous, current); 

README中详细介绍了提供的更多实用程序示例。

在JGit Tutorial中有一些信息(但是它既不是真的有用也不完整,可能已经过时,因为他们切换到没有文档可用的eclipse )。

您可以按如下方式读取给定文件路径的内容。 请注意,如果在给定树中找不到路径,TreeWalk可以为null 。 所以它需要一些特定的处理。

 public String readFile(RevCommit commit, String filepath) throws IOException { try (TreeWalk walk = TreeWalk.forPath(repo, filepath, commit.getTree())) { if (walk != null) { byte[] bytes = repo.open(walk.getObjectId(0)).getBytes(); return new String(bytes, StandardCharsets.UTF_8); } else { throw new IllegalArgumentException("No path found."); } } } 

例如:

 ObjectId head = repo.resolve(Constants.HEAD); RevCommit last = repo.parseCommit(head); readFile(last, "docs/README.md") 

这个答案是用JGit 4.8.0编写的。