【问题标题】:Git fetch failing using jgit: Remote does not have <branchname> available for fetch使用 jgit 获取 Git 失败:远程没有可用于获取的 <branchname>
【发布时间】:2012-07-03 11:48:59
【问题描述】:

我有一个位于 main.git 的裸仓库,我正试图在另一个仓库 test 中获取一个分支(假设是 foo),它刚刚是 git init'd:

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 d=
  • @David:我应该补充一点,我不能使用 git 命令行 - 我必须以编程方式使用它。 (J)Git 实际上是我正在构建的应用程序的一部分,它将在客户端的硬件上运行,并且不会安装 git(我也不想安装它,在 Windows 上设置很痛苦)。他们唯一拥有的就是 Java。

标签: java git version-control jgit git-fetch


【解决方案1】:

应该怎么做:

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 class 提到:

/**
 * 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/”似乎是强制性的。


原答案:

setRemote() function on api.FetchCommand 采用名称或 URI。

查看FetchCommandTest URI 定义,我更喜欢让遥控器更显眼:
我宁愿为您的第二个 repo(引用您的第一个 repo)定义一个命名远程(在下面:“test”),然后获取。

// 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()),这也适用于推送命令。
  • @CallumRogers 我刚刚编辑了答案以在RefSpec 上添加备注。
  • 太棒了!它现在可以工作了 - 正如您正确理解的那样,问题是RefSpec 中的每个分支都需要使用完整的refs/heads/foo!非常感谢。
  • @CallumRogers 太好了。我已经重新组织了答案以使实际的解决方案(大约RefSpec)更加明显。
猜你喜欢
  • 1970-01-01
  • 2019-03-25
  • 2016-02-01
  • 2012-03-21
  • 2013-09-22
  • 2017-10-16
相关资源
最近更新 更多