如何在不克隆的情况下使用 JGIT 将文件夹添加到 GitHub 存储库?

How do I add a folder to a GitHub repo using JGIT without cloning?

如何使用 JGIT 将包含项目的文件夹添加到存储库(在本例中为 GitHub 存储库)而无需克隆等?我是否可以只使用该文件夹创建一个本地存储库,然后将其与远程存储库合并?

我不想克隆的原因是存储库会变得非常大,我不希望克隆需要很长时间。此外,这是在 Spigot 插件命令中,但我认为这不会改变任何东西。当我 运行 命令时它给我一个错误。

最后一件事是当我将文件夹复制到 repo 文件夹时。它只是创建一个名为“Minecraft Servers”的文件夹和其中的文件 none。我做错了什么?

源代码:

public class SaveServer implements CommandExecutor {

    private final CrucialPlugin plugin;

    public SaveServer(CrucialPlugin plugin) {
        this.plugin = plugin;
    }


    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {

        if (sender instanceof Player) {
            Player player = (Player) sender;

            if (args.length == 0) {
                player.sendMessage(ChatColor.RED + "You need to enter some arguments");
                player.sendMessage(ChatColor.YELLOW + "To save the server network to the GitHub repo: /saveserver <what you built/did>");
            } else if (args.length == 1) {
                if (plugin.getConfig().getString("Repository URL") != null && plugin.getConfig().getString("GitHub username") != null && plugin.getConfig().getString("GitHub password") != null) {
                    Path repofolder = Path.of("Server Network Repo");
                    File test = new File(String.valueOf(repofolder));
                    if (Files.exists(repofolder)) {
                        test.delete();
                    }
                    player.sendMessage(ChatColor.GREEN + "Saving server with caption: " + args[0] + "...");
                    File curdir = new File(System.getProperty("user.dir"));
                    Path networkFolder = curdir.toPath().getParent();
                    Path finalFolder = Path.of(repofolder + File.separator + "Minecraft Servers");
                    Date date = new Date();
                    char subColon = '\uA789';
                    String filename = date.toString().replace(':', subColon) + "-" + args[0].toUpperCase().replace("_", " ") + ".txt";

                    File txt = new File(networkFolder + File.separator + filename);
                    try {
                        txt.createNewFile();
                        Git.init().setDirectory(new File("Server Network Repo")).call();
                        Git git = Git.open(new File("Server Network Repo"));
                        git.add().addFilepattern(networkFolder.toString()).call();

                        Files.copy(networkFolder, finalFolder, REPLACE_EXISTING);
                        // add remote repo:
                        RemoteAddCommand remoteAddCommand = git.remoteAdd();
                        remoteAddCommand.setName("origin");
                        remoteAddCommand.setUri(new URIish(plugin.getConfig().getString("Repository URL")));
                        remoteAddCommand.call();

                        // push to remote:
                        PushCommand pushCommand = git.push();
                        pushCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(plugin.getConfig().getString("GitHub username"), plugin.getConfig().getString("GitHub password")));
                        pushCommand.call();
                    } catch (GitAPIException | IOException | URISyntaxException e) {
                        player.sendMessage(ChatColor.RED + "Unable to retrieve repository.");
                    }
                    player.sendMessage("Filename test: " + filename);
                } else {
                    player.sendMessage(ChatColor.RED + "You need to fill in all the fields under Save Server in the configuration file before you can use this feature.");
                }
            } else {
                player.sendMessage(ChatColor.RED + "Too many arguments");
                player.sendMessage(ChatColor.YELLOW + "To save the server network to the GitHub repo: /saveserver <what you built/did>");
            }
        }
        return true;
    }
}

问题似乎可以通过使用浅克隆和稀疏签出来解决,这些 git 功能允许克隆存储库而无需实际提取全部内容和历史记录。问题是截至 2022 年 4 月,该功能尚未在 jGit 中实现。因此,根据您的情况,您可能会做出某种妥协:

  • 如果您可以控制将要执行代码的环境,您可以尝试调用 shell 命令并调用真正的 git 而不是 jgit。这当然会降低解决方案的可移植性,并给环境带来额外的配置负担,(期望安装 git,期望它的版本正确,期望代码 运行 权限足以调用系统命令,git 身份验证现在发生在 Java 代码之外,等等)。

  • 如果您打算只将特定的更新文件推送到主分支的顶部,并且您不关心所有 git 功能,如分支、差异和合并,而只是使用非常具体的 github 存储库作为一种配置存储,有时您需要使用 Java 进行更新,那么您可能希望完全跳过 git,并使用 Github REST API 代替。然后,您将发送更新后的文件和提交信息,例如作为 http POST 请求的消息和作者,并让 Github 将其转换为其他用户可以使用常规 git 的提交] 客户。 API 已经准备好使用 Java 包装器,例如this project。当然,如果你只是碰巧使用了Github,而实际的代码预计会与anygit仓库和服务器后端一起工作,那么这个方法将不会工作。它也有对 API 产生额外依赖的缺点,它不像常规 git 那样稳定,因此由于 Github 的变化,某些东西更有可能被破坏。

  • 从另一个角度解决问题,尽量减少存储库的大小。例如,放弃 git 历史并使每个提交都成为一个修改提交强制推送以覆盖前一个。可能是 git 反模式列表中的前 10 项,并且明显滥用了 git 的意图,但如果它解决了您的问题,那么这一切都是最好的。没有解决存储库大文件大的问题,不仅仅是因为历史悠久。

  • 雇佣一个团队解决this and/or this。很多人都会受益,所以这是一个道德选择。据我所知没有缺点 ;)。