0

I'm trying to clone a repo to the local file system and then checkout a specific commit.
This is what I have:

Git.Clone(GIT_REPO_URL, localPath, CLONE_OPTIONS).then((repo) => {
    return repo.getCommit(version).then((commit) => {
        // use the local tree
    });
}).catch((error) => {
    // handler clone failure
});

This clones the repo just fine, but the local version I end up with is the current head of the master and not the commit I checked out (version).

How do I update the local tree to match this commit?
Thanks.

Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • Don't you need to checkout the commit? Is that what `getCommit` does? Although it would put you in a detached head state... – evolutionxbox Mar 07 '17 at 15:36
  • @evolutionxbox Yeah, that's what the [getCommit](http://www.nodegit.org/api/repository/#getCommit) is for, but it seems not to change the local tree just pass it as an argument to the function. My question is how to update the local tree with that? – Nitzan Tomer Mar 07 '17 at 15:38
  • Just a helpful tip: For proper error handling, you'd want to return the promise given by the `repo.getCommit(...)` chain. As it is now, errors that would occur in, for example, the getCommit error handler itself would go unhandled and may crash your program. – Frxstrem Mar 07 '17 at 15:46
  • @Frxstrem Yeah, thanks, updated my code. – Nitzan Tomer Mar 07 '17 at 15:57

3 Answers3

3

getCommit does not modify the local tree; it merely retrieves the commit in memory in the script, so that you can work with it without modifying the local tree. (This would, for example, be useful if you wanted to walk through the git history and do some analysis, but didn't need to actually update the local tree to access the files themselves.)

To actually check out a specific branch or commit, you want to use the checkoutBranch and checkoutRef functions, which actually do update the local working tree. (Notice how their descriptions explicitly say so, unlike getCommit, which doesn't say it modifies the working three because it doesn't actally do that).

Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • Do you know how to work with `checkoutBranch` and `checkoutRef`? Seems like I need to create a [reference](http://www.nodegit.org/api/reference/) but it's not clear how to do so for a commit version – Nitzan Tomer Mar 07 '17 at 15:57
1

If you want to checkout a random commit, you need to use the Checkout.tree(*) function instead.

var repository;
NodeGit.Clone(GIT_REPO_URL, localPath, CLONE_OPTIONS)
.then(function(repo) {
    repository = repo;
    return repo.getCommit(version);
})
.then(function(commit) {
    return NodeGit.Checkout.tree(repository, commit, checkoutStrategy:
      git.Checkout.STRATEGY.FORCE
    });
}).catch((error) => {
    // handler clone failure
});

You may or may not also want to detach your HEAD.

Edit: This will checkout and set HEAD to the commit in question.

var repository;
NodeGit.Clone(GIT_REPO_URL, localPath, CLONE_OPTIONS)
.then(function(repo) {
    repository = repo;
    return repo.getCommit(version);
})
.then(function(commit) {
    repository.setHeadDetached(commit.id());
}).catch((error) => {
    // handler clone failure
});
rcjsuen
  • 873
  • 1
  • 6
  • 12
0

I haven't managed to make it work, and as it turned out to be way too complicated to get something as trivial to work, I've decided to just do this:

import * as process from "child_process";

const command = `git clone ${ GIT_REPO_URL } ${ repoPath } && cd ${ repoPath } && git checkout ${ version }`;
process.exec(command, error => {
    ...
});
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299