Switch Branch/Tag with nodegit
Asked Answered
G

2

11

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.
        });
    });
});
Glioma answered 10/4, 2015 at 20:11 Comment(2)
You haven't explained what happens when you run that code.Thayer
Nothing happens - no errors thrown. The repo is currently on the master branch, after this executes it is still on the master branch. I want to switch to the v1.0.0 tag.Glioma
F
13

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.

Forefend answered 11/4, 2015 at 4:2 Comment(2)
This got me going and I got help on the gitter channel. Thanks for the direction!Glioma
You should consider adding your findings here, StackOverflow is a place to share knowledge, not just technical support :/Slowworm
S
1

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.

Saintly answered 10/9, 2017 at 11:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.