使用jgit进行Git fetch失败:远程没有可供fetch的<branchname>分支。

5

我有一个位于main.git的裸库,并尝试从另一个仓库test中获取一个分支(例如foo),该仓库刚刚执行了git init操作:

fetchtest/
  |- main.git/
  |- test/
       |- .git/

使用常规的git命令,我可以执行git fetch ../main.git foo:foo,这将在test/中创建一个新的分支foo并获取所需的对象。 然后,我想使用JGit以编程方式执行相同的操作,即不使用git CLI而只使用Java代码。我无法使用git CLI:
Git git = Git.init().setDirectory(new File("fetchtest/test/")).call();

git.fetch().setRemote(new File("../main.git"))
           .setRefSpecs(new RefSpec("foo:foo"))
           .call();

但是它只是出现错误信息:
org.eclipse.jgit.api.errors.TransportException: Remote does not have foo available for fetch.
    at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:137)
    // ......
Caused by: org.eclipse.jgit.errors.TransportException: Remote does not have foo available for fetch.
    at org.eclipse.jgit.transport.FetchProcess.expandSingle(FetchProcess.java:349)
    at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:139)
    at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:113)
    at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1069)
    at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:128)

我该如何让它工作?


你不想要的答案:学习命令行 git。 - dcow
1
@David:我应该补充说明,我不能使用git命令行 - 我必须以编程方式使用它。 (J)Git实际上是我正在构建的应用程序的一部分,它将在客户端硬件上运行,并且git不会被安装(也不想在Windows上安装它,因为设置很麻烦)。他们唯一拥有的就是Java。 - Callum Rogers
1个回答

5

应该起作用的内容:

Git git = Git.init().setDirectory(new File("fetchtest/test/")).call();

git.fetch().setRemote(new File("../main.git"))
           .setRefSpecs(new RefSpec("refs/heads/foo:refs/heads/foo"))
           .call();

请注意RefSpec的定义。
至少在您的示例中尝试:
new RefSpec("refs/heads/foo:refs/heads/foo")

RefSpec提到:

/**
 * Parse a ref specification for use during transport operations.
 * <p>
 * Specifications are typically one of the following forms:
 * <ul>
 * <li><code>refs/head/master</code></li>
 * <li><code>refs/head/master:refs/remotes/origin/master</code></li>
 * <li><code>refs/head/*:refs/remotes/origin/*</code></li>
 * <li><code>+refs/head/master</code></li>
 * <li><code>+refs/head/master:refs/remotes/origin/master</code></li>
 * <li><code>+refs/head/*:refs/remotes/origin/*</code></li>
 * <li><code>:refs/head/master</code></li>
 * </ul>
 *
 * @param spec
 * string describing the specification.
 * @throws IllegalArgumentException
 * the specification is invalid.
*/

所以 "refs/head/" 似乎是必需的。
原始回答:
api.FetchCommand 上,setRemote() 函数接受名称或 URI。
查看
FetchCommandTest 中的 URI 定义,我更喜欢使远程更加可见:
我宁愿为您的第二个仓库(引用第一个仓库)定义一个命名的远程(在此处下面:"test"),然后再进行 fetch。
// setup the first repository to fetch from the second repository
final StoredConfig config = db.getConfig();
RemoteConfig remoteConfig = new RemoteConfig(config, "test");
URIish uri = new URIish(db2.getDirectory().toURI().toURL());
remoteConfig.addURI(uri);
remoteConfig.update(config);
config.save();

// create some refs via commits and tag
RevCommit commit = git2.commit().setMessage("initial commit").call();
Ref tagRef = git2.tag().setName("tag").call();

Git git1 = new Git(db);

RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
git1.fetch().setRemote("test").setRefSpecs(spec)
.call();

谢谢您的答复,我会尝试您的建议。我认为相对路径应该可以工作(实际上我使用 new File(relativePath).getAbsolutePath()),这也适用于推送命令。 - Callum Rogers
@CallumRogers 我刚刚编辑了答案,添加了关于RefSpec的备注。 - VonC
1
太好了!现在它运行正常了 - 问题就像你正确指出的那样,是在每个分支的“RefSpec”中需要使用完整的 refs/heads/foo!非常感谢你。 - Callum Rogers
1
@CallumRogers 非常好。我重新组织了答案,以使实际解决方案(关于“RefSpec”)更加明显。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接