What is the correct way to pull a remote branch to a local branch using libgit2sharp? [duplicate] - libgit2

i try to Checkout a Remotebranch via LibGitSharp. In git itself you use this comands:
git fetch origin
git checkout -b test origin/test
in newer Versions it is just:
git fetch
git checkout test
So i tried this Code:
repo.Fetch("origin");
repo.Checkout("origin/" + Name);
The Fetch and Checkout runs without any problems but there is no copy of the Remotebranch.
Does anyone have an idea to Checkout the Remote with other methods?
My alternative would be to create the Branch in the Repository and push it into Remote:
Branch newBranch = repo.Branches.Add(Name, repo.Branches["master"].Commits.First());
repo.Network.Push(newBranch);
but i get this Exception:
The branch 'Test1' ("refs/heads/Test1") that you are trying to push does not track an upstream branch.
maybe i could set the Branch to an upstream Branch, but i don't know how.
Edit: I haven't explained it properly, so I try to describe it better what the Fetch and Checkout does in my program. The Fetch command is performed correctly. Now if i use the checkout command it should be create an local Branch of the Remotebranch, but it doesn't. I've also tried repo.Checkout(name), without "origin/" ,but it cast an Exception: No valid git object identified by '...' exists in the repository.

If I correctly understand your question, you're willing to create a local branch which would be configured to track the fetched remote tracking branch.
In other words, once you fetch a repository, your references contains remote tracking branches (eg. origin/theBranch) and you'd like to create a local branch bearing the same name (eg. theBranch).
The following example should demonstrate how to do this
const string localBranchName = "theBranch";
// The local branch doesn't exist yet
Assert.Null(repo.Branches[localBranchName]);
// Let's get a reference on the remote tracking branch...
const string trackedBranchName = "origin/theBranch";
Branch trackedBranch = repo.Branches[trackedBranchName];
// ...and create a local branch pointing at the same Commit
Branch branch = repo.CreateBranch(localBranchName, trackedBranch.Tip);
// The local branch is not configured to track anything
Assert.False(branch.IsTracking);
// So, let's configure the local branch to track the remote one.
Branch updatedBranch = repo.Branches.Update(branch,
b => b.TrackedBranch = trackedBranch.CanonicalName);
// Bam! It's done.
Assert.True(updatedBranch.IsTracking);
Assert.Equal(trackedBranchName, updatedBranch.TrackedBranch.Name);
Note: More examples can be found in the BranchFixture.cs test suite.

Related

Travis-CI, how to get committer_email, author_name, within after_script command

I know committer_email, author_name, and load of other variables are part of the notification event. Is it possible to get access to them in earlier events like before_script, after_script?
I would like to get access of the information and add it directly to my test results. Having build information, test result information, and github repo information in the same file would be great.
You can extract committer e-mail, author name, etc. to environment variables using git log with --pretty, e.g.
export COMMITTER_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty="%cE")"
export AUTHOR_NAME="$(git log -1 $TRAVIS_COMMIT --pretty="%aN")"
On Travis one'd put this in the before_install or before_script stage.
TRAVIS_COMMIT environment variable is provided by default.

JGit: Reading commits from a submodule

I am trying to add submodules support to a project of mine, however I seem to be unable to use JGit to read specific commits or to log, while commandline git can do this just fine, despite the detached head that the submodule is in (as far as by design of how submodules work).
I have code like this, with "fuse-jna" being the submodule:
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.setGitDir(new File("fuse-jna/.git"))
.readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build();
ObjectId lastCommitId = repository.resolve("39c1c4b78ff751b0b9e28f4fb35148a1acd6646f");
Iterable<RevCommit> commits = new Git(repository).log().add(lastCommitId).call();
for(RevCommit commit : commits) {
System.out.println("Commit: " + commit.getId());
}
with this I get:
org.eclipse.jgit.errors.MissingObjectException: Missing commit 39c1c4b78ff751b0b9e28f4fb35148a1acd6646f
at org.eclipse.jgit.internal.storage.file.WindowCursor.open(WindowCursor.java:149)
at org.eclipse.jgit.revwalk.RevWalk.getCachedBytes(RevWalk.java:883)
at org.eclipse.jgit.revwalk.RevCommit.parseHeaders(RevCommit.java:145)
at org.eclipse.jgit.revwalk.RevWalk.markStart(RevWalk.java:279)
at org.eclipse.jgit.api.LogCommand.add(LogCommand.java:330)
at org.eclipse.jgit.api.LogCommand.add(LogCommand.java:189)
at org.dstadler.jgitfs.util.JGitHelperTest.testGitLinkRepository(JGitHelperTest.java:638)
However on the commandline in the "fuse-jna" directory
git diff 39c1c4b78ff751b0b9e28f4fb35148a1acd6646f~
works just fine, so it is possible to do this.
Is there some other way how to do this with JGit? Or is support for submodules not fully there yet?
Seems the trick is to not open the repository of the submodule like a normal Git repository, but use the JGit class SubmoduleWalk and the parent-repository to do this!
The following did work for me after playing around with it some more:
Repository subRepo = SubmoduleWalk.getSubmoduleRepository(repository, "fuse-jna");

How to remove a 'branch' in tortoise HG

I accidentally updated to a previous revision, and committed from it under the default branch, causing 2 heads under the default branch. I want to move one of the heads to another branch. This head I want to move was made a couple transactions ago. How can I change the branch it is a part of so that I can push the other head to the server without a force push?
I have not pushed anything to the server so far. If it comes down to it, I can copy the files I need and reclone the repository.
Rebase
Graft (move to new place) + Histedit (kill old changeset)
MQ, if you know it (convert cset to MQ-patch, update to new parent, qpop, qfinish)
You can rewrite the history with the rebase extension. It's already installed, you just need to enable it (from File > Settings > Extensions in tortoiseHG). Inside tortoiseHG you can find it if you right-click on a revision, go to "Modify History", and choose "rebase". But for more control I recommend dropping to the commandline.
Let's say you have a revision w that's a new head off the default branch. (w might have descendants which will move along with it).
-o-o-o-o
\
w
Its parent should have been some revision b in another branch (not shown). Just enter:
hg rebase --source w --dest b --detach
That's it! It will rebase w and all of its descendants (if any), so that its new parent is b. It will be assigned to the same branch name as b, unless you add --keepbranches. The flag --detach ensures that you don't end up with a complex topology under some circumstances.

GitHub v3 API - how do I create the initial commit in a repository?

I'm using the v3 API and managed to list repos/trees/branches, access file contents, and create blobs/trees/commits. I'm now trying to create a new repo, and managed to do it with "POST user/repos"
But when I try to create blobs/trees/commits/references in this new repo I get the same error message. (409) "Git Repository is empty.". Obviously I can go and init the repository myself through the git command line, but would rather like if my application did it for me.
Is there a way to do that? What's the first thing I need to do through the API after I create an empty repository?
Thanks
Since 2012, it is now possible to auto initialize a repository after creation, according to this blog post published on the GitHub blog:
Today we’ve made it easier to add commits to a repository via the GitHub API. Until now, you could create a repository, but you would need to initialize it locally via your Git client before adding any commits via the API.
Now you can optionally init a repository when it’s created by sending true for the auto_init parameter:
curl -i -u pengwynn \
-d '{"name": "create-repo-test", "auto_init": true}' \
https://api.github.com/user/repos
The resulting repository will have a README stub and an initial commit.
Update May 2013: Note that the repository content API now authorize adding files.
See "File CRUD and repository statistics now available in the API".
Original answer (May 2012)
Since it doesn't seems to be supported yet ("GitHub v3 API: How to create initial commit for my shiny new repository?", as aclark comments), you can start by pushing an initial empty commit
git commit --allow-empty -m 'Initial commit'
git push origin master
That can be a good practice to initialize one's repository anyway.
And it is illustrated in "git's semi-secret empty tree".
If you want to create an empty initial commit (i.e. one without any file) you can do the following:
Create the repository using the auto_init option as in Jai Pandya's answer; or, if the repository already exists, use the create file endpoint to create a dummy file - this will create the branch:
PUT https://api.github.com/repos/USER/REPO/contents/dummy
{
"branch": "master",
"message": "Create a dummy file for the sake of creating a branch",
"content": "ZHVtbXk="
}
This will give you a bunch of data including a commit SHA, but you can discard all of it since we are about to obliterate that commit.
Use the create commit endpoint to create a commit that points to the empty tree:
POST https://api.github.com/repos/USER/REPO/git/commits
{
"message": "Initial commit",
"tree": "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
}
This time you need to take note of the returned commit SHA.
Use the update reference endpoint to make the branch point to the commit you just created (notice the Use Of The ForceTM):
PATCH https://api.github.com/repos/USER/REPO/git/refs/heads/master
{
"sha": "<the SHA of the commit>",
"force": true
}
Done! Your repository has now one branch, one commit and zero files.
2023 January: The 2. step of Konamiman's solution did not work for me, unless I deleted the dummy file with the contents api:
DELETE https://api.github.com/repos/USER/REPO/contents/dummy
{
"branch": "master",
"message": "Delete dummy file",
"sha": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
}
(This sha is for the empty content "".)
After deleting the dummy file somehow 4b825dc642cb6eb9a060e54bf8d69288fbee4904 becomes assignable to a new commit.
It looks like over time this changed. It feels bad to rely on undocumented API behavior. :(

Using sub-repo with hgwebdir difficulties in mercurial

Allright I got myself in a deadlock with Mercurial and sub-repos... Here's what happenend:
I had a large mercurial repo that I server via apache and hgweb.cgi.
Due to the size of the repo I decided to move to sub-repositories and share these with hgwebdir.cgi.
Using the convert tool with the filemap option I created several sub-repositories:
/main/foo
/main/bar
Nicely created an entry for the sub-repositories in .hgsub:
foo = foo
bar = bar
And set hgwebdir.cgi up to show $/** as the root folder.
Now when I went to my site (foo.com/hg) I saw my sub-repositories with one empty reposory among them (no name, no content), but I could not download it (archive location unknown):
empty_repo http://img707.imageshack.us/img707/8237/emptysubrepo.png
That was allright until I added a new sub-repository.
I could not push the new .hgsub file to foo.com/hg, since that page is served by hgwebdir.
The only method I can work currently is switch from hgwebdir to hgweb, commit .hgsubste and switch back to hgwebdir.
Does someone have a good setup for such a mess?
On the webserver your main and its subrepos should appear as siblings -- not with the subrepos inside main.
Main
ASCII
AlignDistribute
And the URLs in your .hgsub should look like:
ASCII = ../ASCII
AlignDistribute = ../AlignDsitribute
Then you'll be able to push/pull to http://foo.com/hg/Main and when you clone it the clone/update will automatically attach and clone down the separate subrepos.
From what I've read on https://www.mercurial-scm.org/wiki/PublishingRepositories#multiple
The keys (on the left) and the values (on the right) are both filesystem paths
The keys should be prefixes of the values and are "subtracted" from the values in order to generate the URL paths to each repository
What I'm guessing happened is that in your hgweb(dir) configuration you're specifying the same value for a collection possibly as the key, so during subtraction it ends up with a blank name and no way to get to it.
When I use [collections] to set /a/full/path = /a/full/path directly to a repo, it'll end up blank too, because it's reading that folder as a repo because it is a repo, instead of each sub-directory being an individual repo, after I removed the .hg folder and .hgsubs and everything from the root of my collection entry, all the subfolders started showing up properly.
I originally used in [paths], /path/to/my/project = /path/to/my/project, and since that is a single referenced repository, it'll subtract the value from the key, leaving you once again with '', instead I used project = /path/to/my/project and it came out as 'project'.
Hopefully that URL or these descriptions will get you out of your pickle!