Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switch Branch/Tag with nodegit

I have been trying all morning to open an existing repo and change branch or tag using nodegit. The documentation is extensive but seems to be out of date. Any ideas on what I'm doing wrong?

var NodeGit = require("nodegit");
var open = NodeGit.Repository.open;
var Tag = NodeGit.Tag;
var Checkout = NodeGit.Checkout;

open(location).then(function (repo) {
    Tag.list(repo).then(function(array) {
        // array is ['v1.0.0']
        var ref = array[0]
        Checkout.tree(repo, ref).then(function() {
            // Want tag to be checked out out in detached state.
        });
    });
});
like image 408
ngourley Avatar asked Apr 10 '15 20:04

ngourley


People also ask

How to switch branches in Git?

By the end of this tutorial, you will know how you can safely commit your work in one branch, switch to another and start working on another feature. The easiest way to switch branch on Git is to use the “ git checkout ” command and specify the name of the branch you want to switch to.

How to switch to a new branch from a specific commit?

In some cases, you may need to switch to a new branch, but you want it to start from a specific commit on the branch. In order to checkout a new branch from a specific start point, you have to execute the “git checkout” command and specify the “-B” option, as well as the branch and its start point. $ git checkout -B <branch> <start_point>

How do I fix Git switch non-existing-branch error?

$ git switch non-existing-branch fatal: invalid reference: non-existing-branch To solve this error, make sure to append the “-c” option to the “git switch” command to specify that you want to switch to a new branch. $ git switch -c non-existing-branch Switched to a new branch 'non-existing-branch'

How to checkout the remote branch in Git?

In order to checkout the remote branch, you will need to execute the checkout command and specify the information specified above. $ git checkout -t origin/remote-branch Branch 'remote-branch' set up to track remote branch 'remote-branch' from 'origin'.


2 Answers

So there are a few things you're missing with your code. First one is that you aren't terminating the promise chain so errors are being swallowed. You'll want to end it with either a .catch or a .done.

Second, I think you're not quite sure what a checkout does. One of the confusing things with low-level git and how it differs from git CLI is that Checkout only updates your working directory to reflect the tree pointed to by the second parameter.

Third, you're passing in a string to a method that is expecting something else. The docs are showing that it's looking for an Oid, Tree, Commit, or Reference. Let's spruce up that code a bit.

var NodeGit = require("nodegit");
var open = NodeGit.Repository.open;
var Tag = NodeGit.Tag;
var Checkout = NodeGit.Checkout;

open(location).then(function (repo) {
  return Tag.list(repo)
    .then(function(array) {
      // array is ['v1.0.0','v2.0.0']
      return Tag.lookup(repo,array[0]);
    })
    .then(function(tag) {
      return Checkout.tree(repo, tag.targetId(), { checkoutStrategy: Checkout.STRATEGY.SAFE_CREATE})
        .then(function() {
          repo.setHeadDetached(tag.targetId(), repo.defaultSignature, "Checkout: HEAD " + tag.targetId());
        });
     });
})
.catch(function(error) {
  // log error
});

That should point you in the right direction. If you need more help I would recommend stopping by our gitter channel where we are pretty active.

like image 80
johnhaley81 Avatar answered Oct 23 '22 09:10

johnhaley81


The following complete solution works for me for tags, which can be either lightweight or annotated tags: (repo is an open repository, tag is the name of the tag to checkout)

var Git = require("nodegit"); 

function checkOutTag(repo, tag) {
    return Git.Reference
      .dwim(repo, "refs/tags/" + tag)
      .then(function (ref) {
          return ref.peel(Git.Object.TYPE.COMMIT);
      })
      .then(function (ref) {
          return repo.getCommit(ref);
      })
      .then(function (commit) {
          return Git.Checkout
            .tree(repo, commit, {checkoutStrategy: Git.Checkout.STRATEGY.SAFE})
            .then(function () {
                return repo.setHeadDetached(commit, repo.defaultSignature, 
                                            "Checkout: HEAD " + commit.id());
          })
    });
 }

It could be easier by using repo.getReferenceCommit(), but this command currently fails for annotated tags. See also https://github.com/nodegit/nodegit/issues/1370 which tracks this issue.

like image 1
Roland Huß Avatar answered Oct 23 '22 09:10

Roland Huß