如何通过JGit访问私有GitHub仓库并遍历文件目录
问题1:解决私有GitHub仓库的授权异常
GitHub目前已不再支持使用账号密码进行HTTPS方式的仓库访问,必须使用**个人访问令牌(PAT)**替代密码。你需要做以下两处代码修改:
替换CredentialsProvider的参数
将原来的账号密码替换为:用户名填你的GitHub账号名,密码填你的个人访问令牌(注意PAT需要勾选repo权限)。如果不想填写用户名,也可以直接将PAT作为用户名,密码留空,两种方式都有效。为第二个
lsRemoteRepository调用添加CredentialsProvider
你代码中第二个callAsMap()的调用没有设置CredentialsProvider,这会导致同样的授权失败,必须补上。
修改后的核心代码片段:
// 替换为你的GitHub用户名和个人访问令牌 private static final String username = "你的GitHub账号名"; private static final String PAT = "你的个人访问令牌"; // 第一个LsRemoteCommand保持设置CredentialsProvider LsRemoteCommand cmd = Git.lsRemoteRepository(); cmd.setHeads(true); cmd.setTags(true); cmd.setRemote(usedURL); cmd.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, PAT)); // 第二个callAsMap()必须添加CredentialsProvider final Map<String, Ref> map = Git.lsRemoteRepository() .setHeads(true) .setTags(true) .setRemote(usedURL) .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, PAT)) .callAsMap();
问题2:遍历远程仓库目录树并查看文件内容
要遍历远程仓库的目录树,你不需要完整克隆仓库,可以通过JGit直接获取远程仓库的树对象并递归遍历。以下是完整的示例代码,包含授权、获取指定分支的目录树和读取文件内容的逻辑:
package com.example.proofOfConceptGitHub.domain; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.*; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Collection; public class RemoteRepoTreeTraversal { private static final String REPO_URL = "https://github.com/wjcasperson/pet-clinic"; private static final String username = "你的GitHub账号名"; private static final String PAT = "你的个人访问令牌"; // 指定要遍历的分支,比如main或master private static final String TARGET_BRANCH = "main"; public static void main(String[] args) throws GitAPIException, IOException { // 步骤1:获取远程仓库的分支引用,找到目标分支的ObjectId UsernamePasswordCredentialsProvider credentials = new UsernamePasswordCredentialsProvider(username, PAT); Collection<Ref> refs = Git.lsRemoteRepository() .setHeads(true) .setRemote(REPO_URL) .setCredentialsProvider(credentials) .call(); ObjectId branchObjectId = null; for (Ref ref : refs) { if (ref.getName().equals("refs/heads/" + TARGET_BRANCH)) { branchObjectId = ref.getObjectId(); break; } } if (branchObjectId == null) { System.err.println("未找到目标分支:" + TARGET_BRANCH); return; } // 步骤2:打开远程仓库的对象数据库,获取树对象 try (Repository repo = Git.lsRemoteRepository() .setRemote(REPO_URL) .setCredentialsProvider(credentials) .open()) { // 获取分支HEAD对应的commit对象 RevCommit commit = repo.parseCommit(branchObjectId); // 获取commit对应的根树 RevTree rootTree = commit.getTree(); // 步骤3:递归遍历目录树 System.out.println("开始遍历仓库目录树:"); traverseTree(repo, rootTree, ""); } } /** * 递归遍历树对象,打印目录和文件,并读取文件内容 */ private static void traverseTree(Repository repo, RevTree tree, String parentPath) throws IOException { try (TreeWalk treeWalk = new TreeWalk(repo)) { treeWalk.addTree(tree); treeWalk.setRecursive(false); treeWalk.setFilter(PathFilter.create(parentPath)); while (treeWalk.next()) { String path = treeWalk.getPathString(); ObjectId objectId = treeWalk.getObjectId(0); ObjectLoader loader = repo.open(objectId); if (treeWalk.isSubtree()) { // 是文件夹,递归遍历 System.out.println("[目录] " + path); traverseTree(repo, repo.parseTree(objectId), path); } else { // 是文件,打印路径并读取内容 System.out.println("[文件] " + path); // 读取文件内容(小文件适用,大文件建议用流处理) ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); loader.copyTo(outputStream); System.out.println("文件内容预览:"); System.out.println(new String(outputStream.toByteArray())); System.out.println("----------------------------------------"); } } } } }
代码说明
- 授权部分:全程使用
UsernamePasswordCredentialsProvider传递GitHub账号和PAT,确保所有远程操作都通过授权验证。 - 分支获取:通过
lsRemoteRepository获取远程分支的引用,定位到目标分支的提交ID。 - 树遍历:使用
TreeWalk递归遍历仓库的树结构,区分文件夹和文件,对于文件直接读取并打印内容。 - 注意事项:如果仓库中有大文件,建议使用
loader.openStream()替代copyTo(),避免内存溢出。
内容的提问来源于stack exchange,提问作者RepairmanBill
相关产品推荐
相关产品推荐

