I have a bare repo located at main.git
and am trying to fetch a branch (foo
, let's say) in another repo, test
, which has only just been git init
'd:
fetchtest/
|- main.git/
|- test/
|- .git/
Using regular git commands, I can do a git fetch ../main.git foo:foo
and this will make a new branch foo
in test/
and fetch the objects required for the branch. I then want to do the same thing but programmatically using JGit, ie not using the git CLI but using only Java code. There is no way I can use the 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();
but it just errors with:
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)
How do I get this to work?
Git fetch commands and optionsFetch all of the branches from the repository. This also downloads all of the required commits and files from the other repository. Same as the above command, but only fetch the specified branch. The --dry-run option will perform a demo run of the command.
git fetch is the command that tells your local git to retrieve the latest meta-data info from the original (yet doesn't do any file transferring. It's more like just checking to see if there are any changes available). git pull on the other hand does that AND brings (copy) those changes from the remote repository.
git fetch allows you to retrieve updated changes from the remote repository and review them, without affecting your local working copy. This is useful if you just wish to take a look at what your team is working on, but keep your own code exactly as it is.
git fetch updates your remote-tracking branches under refs/remotes/<remote>/ . This operation is safe to run at any time since it never changes any of your local branches under refs/heads .
What should work:
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();
Note the RefSpec
definition.
At least, try in your example:
new RefSpec("refs/heads/foo:refs/heads/foo")
The RefSpec
class mentions:
/**
* 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.
*/
So "refs/head/
" seems mandatory.
Original answer:
The setRemote()
function on api.FetchCommand
takes a name or an URI.
And looking at the FetchCommandTest
URI definition, I prefer making the remote more visible:
I would rather define a named remote (here below: "test
") for your second repo (referring your first repo), and then 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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With