You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:25:14