I am trying to create a remote branch with jgit, which executes exactly the following git commands:
git clone git#gitlab.com:my-project/test.git
git checkout -b superBranch
git push --set-upstream origin superBranch
After these executions, I can change and push the files of the branch without merge request.
jGit:
Unfortunately jgit does not know the command "push -u" (Upstream). So I found some maybe solution. But all solutions does not work really.
First in StackOverflow:
// git clone done, than:
git.branchCreate()
.setName("superBranch")
.setForce(true)
.setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
.setStartPoint("origin/superBranch").call(); // <-- Ref not found
RefSpec refSpec = new RefSpec().setSourceDestination("superBranch", "superBranch");
git.push()
.setRefSpecs(refSpec)
.setCredentialsProvider(provider).call();
git.checkout().setName("superBranch").call();
Exception:
org.eclipse.jgit.api.errors.RefNotFoundException: Ref origin/superBranch cannot be resolved
Another solution I found here Eclipse Forum:
git.branchCreate().setName("superBranch").call();
git.push()
.setRemote("origin")
.setRefSpecs(new RefSpec("superBranch" + ":" + "superBranch")) //<-- Ref not found
.setCredentialsProvider(provider).call();
git.branchCreate()
.setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.SET_UPSTREAM)
.setStartPoint("origin/" + "superBranch")
.setForce(true).call();
git.checkout().setName("superBranch").call();
Exception:
org.eclipse.jgit.api.errors.InvalidRefNameException: Branch name <null> is not allowed
Does anyone know how can I create a remote and local branch, without call an api or make a merge request like my git example on the top?
Following code works for me:
Git git = Git.cloneRepository()
.setURI("https://gitlab.com/my-project/test.git")
.setDirectory(new File("scratch/test"))
.setCloneAllBranches(true)
.setCredentialsProvider(provider).call();
git.checkout()
.setCreateBranch(true)
.setName(BRANCH).call();
git.push()
.setRemote("origin")
.setRefSpecs(new RefSpec(BRANCH + ":" + BRANCH))
.setCredentialsProvider(provider).call();
So I clone the repository, checkout the branch or create the branch if not exits, then I push the new branch to the remote repository.
Finally, I tried this, that works for me.
git.branchCreate().setName(localBranchName).call();
git.push().setRemote("origin")
.setCredentialsProvider(createCredential(name, password))
.setRefSpecs(new RefSpec(localBranchName + ":" + localBranchName)).call();
//delete is necessary
git.branchDelete().setBranchNames(localBranchName).call();
git.checkout().setCreateBranch(true).setName(localBranchName)
.setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
.setStartPoint("origin/" + localBranchName)
.call();
If I had 20 directories under trunk/ with lots of files in each and only needed 3 of those directories, would it be possible to do a Subversion checkout with only those 3 directories under trunk?
Indeed, thanks to the comments to my post here, it looks like sparse directories are the way to go. I believe the following should do it:
svn checkout --depth empty http://svnserver/trunk/proj
svn update --set-depth infinity proj/foo
svn update --set-depth infinity proj/bar
svn update --set-depth infinity proj/baz
Alternatively, --depth immediates instead of empty checks out files and directories in trunk/proj without their contents. That way you can see which directories exist in the repository.
As mentioned in #zigdon's answer, you can also do a non-recursive checkout. This is an older and less flexible way to achieve a similar effect:
svn checkout --non-recursive http://svnserver/trunk/proj
svn update trunk/foo
svn update trunk/bar
svn update trunk/baz
Subversion 1.5 introduces sparse checkouts which may be something you might find useful. From the documentation:
... sparse directories (or shallow checkouts) ... allows you to easily check out a working copy—or a portion of a working copy—more shallowly than full recursion, with the freedom to bring in previously ignored files and subdirectories at a later time.
I wrote a script to automate complex sparse checkouts.
#!/usr/bin/env python
'''
This script makes a sparse checkout of an SVN tree in the current working directory.
Given a list of paths in an SVN repository, it will:
1. Checkout the common root directory
2. Update with depth=empty for intermediate directories
3. Update with depth=infinity for the leaf directories
'''
import os
import getpass
import pysvn
__author__ = "Karl Ostmo"
__date__ = "July 13, 2011"
# =============================================================================
# XXX The os.path.commonprefix() function does not behave as expected!
# See here: http://mail.python.org/pipermail/python-dev/2002-December/030947.html
# and here: http://nedbatchelder.com/blog/201003/whats_the_point_of_ospathcommonprefix.html
# and here (what ever happened?): http://bugs.python.org/issue400788
from itertools import takewhile
def allnamesequal(name):
return all(n==name[0] for n in name[1:])
def commonprefix(paths, sep='/'):
bydirectorylevels = zip(*[p.split(sep) for p in paths])
return sep.join(x[0] for x in takewhile(allnamesequal, bydirectorylevels))
# =============================================================================
def getSvnClient(options):
password = options.svn_password
if not password:
password = getpass.getpass('Enter SVN password for user "%s": ' % options.svn_username)
client = pysvn.Client()
client.callback_get_login = lambda realm, username, may_save: (True, options.svn_username, password, True)
return client
# =============================================================================
def sparse_update_with_feedback(client, new_update_path):
revision_list = client.update(new_update_path, depth=pysvn.depth.empty)
# =============================================================================
def sparse_checkout(options, client, repo_url, sparse_path, local_checkout_root):
path_segments = sparse_path.split(os.sep)
path_segments.reverse()
# Update the middle path segments
new_update_path = local_checkout_root
while len(path_segments) > 1:
path_segment = path_segments.pop()
new_update_path = os.path.join(new_update_path, path_segment)
sparse_update_with_feedback(client, new_update_path)
if options.verbose:
print "Added internal node:", path_segment
# Update the leaf path segment, fully-recursive
leaf_segment = path_segments.pop()
new_update_path = os.path.join(new_update_path, leaf_segment)
if options.verbose:
print "Will now update with 'recursive':", new_update_path
update_revision_list = client.update(new_update_path)
if options.verbose:
for revision in update_revision_list:
print "- Finished updating %s to revision: %d" % (new_update_path, revision.number)
# =============================================================================
def group_sparse_checkout(options, client, repo_url, sparse_path_list, local_checkout_root):
if not sparse_path_list:
print "Nothing to do!"
return
checkout_path = None
if len(sparse_path_list) > 1:
checkout_path = commonprefix(sparse_path_list)
else:
checkout_path = sparse_path_list[0].split(os.sep)[0]
root_checkout_url = os.path.join(repo_url, checkout_path).replace("\\", "/")
revision = client.checkout(root_checkout_url, local_checkout_root, depth=pysvn.depth.empty)
checkout_path_segments = checkout_path.split(os.sep)
for sparse_path in sparse_path_list:
# Remove the leading path segments
path_segments = sparse_path.split(os.sep)
start_segment_index = 0
for i, segment in enumerate(checkout_path_segments):
if segment == path_segments[i]:
start_segment_index += 1
else:
break
pruned_path = os.sep.join(path_segments[start_segment_index:])
sparse_checkout(options, client, repo_url, pruned_path, local_checkout_root)
# =============================================================================
if __name__ == "__main__":
from optparse import OptionParser
usage = """%prog [path2] [more paths...]"""
default_repo_url = "http://svn.example.com/MyRepository"
default_checkout_path = "sparse_trunk"
parser = OptionParser(usage)
parser.add_option("-r", "--repo_url", type="str", default=default_repo_url, dest="repo_url", help='Repository URL (default: "%s")' % default_repo_url)
parser.add_option("-l", "--local_path", type="str", default=default_checkout_path, dest="local_path", help='Local checkout path (default: "%s")' % default_checkout_path)
default_username = getpass.getuser()
parser.add_option("-u", "--username", type="str", default=default_username, dest="svn_username", help='SVN login username (default: "%s")' % default_username)
parser.add_option("-p", "--password", type="str", dest="svn_password", help="SVN login password")
parser.add_option("-v", "--verbose", action="store_true", default=False, dest="verbose", help="Verbose output")
(options, args) = parser.parse_args()
client = getSvnClient(options)
group_sparse_checkout(
options,
client,
options.repo_url,
map(os.path.relpath, args),
options.local_path)
Or do a non-recursive checkout of /trunk, then just do a manual update on the 3 directories you need.
If you already have the full local copy, you can remove unwanted sub folders by using --set-depth command.
svn update --set-depth=exclude www
See: http://blogs.collab.net/subversion/sparse-directories-now-with-exclusion
The set-depth command support multipile paths.
Updating the root local copy will not change the depth of the modified folder.
To restore the folder to being recusively checkingout, you could use --set-depth again with infinity param.
svn update --set-depth=infinity www
I'm adding this information for those using the TortoiseSvn tool: to obtain the OP same functionality, you can use the Choose items... button in the Checkout Depth section of the Checkout function, as shown in the following screenshot:
Sort of. As Bobby says:
svn co file:///.../trunk/foo file:///.../trunk/bar file:///.../trunk/hum
will get the folders, but you will get separate folders from a subversion perspective. You will have to go separate commits and updates on each subfolder.
I don't believe you can checkout a partial tree and then work with the partial tree as a single entity.
Not in any especially useful way, no. You can check out subtrees (as in Bobby Jack's suggestion), but then you lose the ability to update/commit them atomically; to do that, they need to be placed under their common parent, and as soon as you check out the common parent, you'll download everything under that parent. Non-recursive isn't a good option, because you want updates and commits to be recursive.
I have a problem where i cannot create local branch.
Error: org.eclipse.jgit.api.errors.RefNotFoundException: Ref origin/sideMerge cannot be resolved
I have checked the following topics and some others in Stackoverflow but it seems something fishy going on or something i don't understand yet.
Can someone point me to a direction what i don't understand regarding the Ref ?
As far as i know the local refs starts from origin/"other_branch"
Code snippet:
Git git;
CreateBranchCommand tmpCreateBranch;
git = new Git(existingRepo);
tmpCreateBranch = git.branchCreate();
try {
tmpCreateBranch.setName(tmpBranchName).setStartPoint("origin/" + tmpBranchName).setForce(true).call();
} catch (Exception e) {
System.out.println("Error in Branch creation");
System.out.println(e);
}
According to Git manual, you can create a branch using the following syntax. It creates a new branch head named <branchname> which points to the current HEAD, or <start-point> if given:
git branch [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
Therefore, you can create a local branch "topic" by following the similar syntax in JGit (see next code-block). In this case, you didn't configure the start-point explicitly. JGit will use HEAD as start-point. So everything works fine:
git.branchCreate().setName("topic").call();
However, if you create a local branch with start-point origin/topic, JGit will try to find this reference in Git References. In this context, origin is the name of the remote, and topic is the name of the branch. If not found, it raises an exception:
git.branchCreate().setName("topic").setStartPoint("origin/topic").call();
You also need to be aware that:
setForce(true) will reset the target branch name to start-point if branch name exists already. Without -f,--force git branch refuses to change an existing branch.
Szilágyi István, I create the branch as follows:
try (Git git = new Git(repository)) {
Ref ref = git.branchCreate().setName("Name_Branch").setStartPoint("origin/develop").call();
git.checkout().setName(branch).call();
git.push().setCredentialsProvider(userService.getCredencialsProvider()).call();
logger.info("Branch created: " + ref + " - " + ref.getName() + " - " + ref.getObjectId().getName());
}
In my Skylark rule, I am looking through all my deps - some of them are maven_jar instances defined in my WORKSPACE file. For those, I would like to access the value of maven_jar.artifact, but as far as I can tell it isn't available. Is it possible to get at that value?
For example, if my WORKSPACE has:
maven_jar(
name = "com_google_guava_guava",
artifact = "com.google.guava:guava:20.0",
)
And my BUILD file has something like this:
my_rule(
name = "foo",
deps = ["#com_google_guava_guava//jar"]
)
In the implementation of my_rule, I would like to get the value com.google.guava:guava:20.0.
I think you'll need to file a feature request for this:
https://github.com/bazelbuild/bazel/issues/new
The instance of the maven_jar rule in the workspace file isn't available to the rules in BUILD files, only the rules which the workspace rule generates are (i.e., #com_google_guava_guava//jar). Off the top of my head, maven_jar would have to generate a rule into the jar's workspace which has an attribute with the value of artifact, and that rule would need to create a provider containing that value for other rules to consume.
(There does happen to be META-INF/maven/com.google.guava/guava/pom.xml inside the jar, which seems to have the information you want, but I don't know if you can rely on that for all jars from maven, but either way, the contents of the jar aren't available at analysis time (within the rule implementation))
I'm trying to pull the remote master branch in my currently checked out local branch. Here's the code for it
checkout.setName(branchName).call();
PullCommand pullCommand = git.pull();
System.out.println("Pulling master into " + branchName + "...");
StoredConfig config = git.getRepository().getConfig();
config.setString("branch", "master", "merge", "refs/heads/master");
pullCommand.setRemote("https://github.com/blackblood/TattooShop.git");
pullCommand.setRemoteBranchName("master");
pullResult = pullCommand.setCredentialsProvider(credentialsProvider).call();
When I run the code I get the following error on this line pullCommand.setRemote("https://github.com/blackblood/TattooShop.git");
Error :
org.eclipse.jgit.api.errors.InvalidConfigurationException:
No value for key remote.https://github.com/blackblood/TattooShop.git.url found in configurationCouldn't pull from remote. Terminating...
at org.eclipse.jgit.api.PullCommand.call(PullCommand.java:247)
at upload_gen.Launcher.updateFromRemote(Launcher.java:179)
at upload_gen.Launcher.main(Launcher.java:62)
Following are the contents of my .git/config file
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "origin"]
url = https://github.com/blackblood/TattooShop.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[remote "heroku"]
url = git#heroku.com:tattooshop.git
fetch = +refs/heads/*:refs/remotes/heroku/*
This seems to be a bug in JGit. According to the JavaDoc of setRemote(), it sets the remote (uri or name) to be used for the pull operation but apparently only the remote name works.
Given your configuration you can work around the issue by using the remote name like this:
pullCommand.setRemote( "origin" );
I recommend to open a bug report in the JGit bugzilla so that this gets fixed in future versions of JGit.