0

I am using nodegit to checkout from clone and Open it to do something. My code like this:

//repo is a Repository from Clone() or Open()
//branchName is your branch name, of course
repo.getBranch('refs/remotes/origin/' + branchName)
    .then(function(reference) {
        //checkout branch
        return repo.checkoutRef(reference);
    });

But after that I cd in to branch directory and typing the command like this

git status
or git branch

It's show a red line like this

HEAD detached at origin/branchname

How can I solved it? Thanks

cauchuyennhocuatoi
  • 461
  • 3
  • 8
  • 21
  • What's the value of `reference`? It should be `branchname` only. `refs/heads/branchname` or `origin/branchname` or `refs/remotes/origin/branchname` lead to a detached HEAD. – ElpieKay Mar 09 '21 at 06:17
  • The value of ref (reference) is: refs/remotes/origin/branchname – cauchuyennhocuatoi Mar 09 '21 at 06:23
  • But if i cannot checkout specific branch by nodegit, do you know another way? I cannot do like that: "return repo.getBranch(branchName);", so I have to do with: "return repo.getBranch('refs/remotes/origin/'+ branchName);" – cauchuyennhocuatoi Mar 09 '21 at 06:27
  • I'm completely new to node.js. Is it possible to run something like `return repo.checkoutRef(reference.replace('refs/remotes/origin/', ''))` in Python? The method is to replace `refs/remotes/origin/` with the empty string. A more reliable way is some method corresponding to the command `git checkout -b branchname refs/remotes/origin/branchname`. BTW, a detached HEAD is not an error. – ElpieKay Mar 09 '21 at 06:35

1 Answers1

1

In general,1 origin/somebranch is not a branch name, and therefore git checkout origin/somebranch results in a detached HEAD, exactly as you are seeing.

Branch names, in Git, don't really do any good, to a first approximation.2 So there's no need to use them. To understand how and why this is the case, let's note that in Git, there are many kinds of names.

A branch name is simply a name which, when spelled out in full, begins with refs/heads/. The branch names master or main, for instance, are really refs/heads/master and refs/heads/main, correspondingly.

A tag name is a name which, when spelled out in full, begins with refs/tags/. So v2.1 is really refs/tags/v2.1.

Git calls these things—these names in general, before they're split into some particular classification—refs or references. Each reference holds one (1) hash ID. The hash ID is what really matters to Git. That's what Git needs. That's what git checkout requires: a hash ID. You can give it any valid commit hash ID, and it will check out that commit.

Hash IDs, though, are big and ugly and look random (though they're not). They are thoroughly unmemorable. What commit is 225365fb5195e804274ab569ac3cc4919451dc7f anyway? If I say v2.31.0-rc0, that probably means something—or at least, seems suggestive of something—to you; but if I say 2253blah you have probably forgotten the 2253 part long before I get to the dc7f part. So refs are for humans. They're not for Git, which only really cares about the hash IDs.

You only need a ref—such as a branch name—if you're a human. If you're a build system, a hash ID is fine. If you're writing part of a build system, just use a hash ID. If you're writing something for a human to use ... well, humans are hard.

Git has a special thing it calls "DWIM", or Do What I Mean, mode. If you run:

git checkout foobranch

and there is no branch named foobranch right now, Git will assume that you mean: Find me a name that resembles foobranch, such as origin/foobranch. Then use that name to make a branch name for me. You can disable this with git checkout --no-guess and sometimes that's a good idea. But sometimes this DWIM mode is exactly what you want.

Note, however, that if the pesky human went and made his own foobranch earlier, not related to origin/foobranch, this git checkout foobranch will get his foobranch, not related to origin/foobranch. So be careful: humans are tricky and weird. They do illogical, unexpected things.

Now, there's a reason humans often want to use a branch name, rather than any other name that results in the detached-HEAD mode. The primary reason they like this is because then, if they make a new commit, Git will change the hash ID stored in the branch name. The new commit will automatically link, backwards, to whatever commit was the one stored in the reference. Then Git will update the branch name so that it now stores the hash ID of the new commit.

This feature is exclusive to branch names. No other kind of name has this special feature. You can select detached-HEAD mode when using a branch name, by running git checkout --detach foobranch for instance. But the default is that when you use git checkout with a branch name—even one that DWIM mode is going to have to create—Git will instead go into attached HEAD mode.3 So that's why humans like branch names, and that's what Git does with them, that it doesn't do with any other reference name.

If you need to accommodate humans, you can do that by letting the DWIM mode do its thing here. That won't satisfy all humans, so watch out. It also won't work in some cases, so watch out. The detached-HEAD mode always works, though.

In NodeGit specifically, you have Branch.create as an async class method of Branch.. You also have Branch.lookup. You could use this to look up a remote-tracking name, like origin/branchname, and use that to create a new local branch, if that's your goal. But as before, watch out for all these various edge cases.


1It is possible to make a (local) branch named origin/somebranch, so that it is a branch name. The result is very confusing unless you carefully call out all names using their full spellings. Don't do this!

2Of course, they do do some good, so the first approximation is pretty rough.

3Git does not call it this, but what else could the right phrase for "opposite of detached HEAD" mode be?

torek
  • 448,244
  • 59
  • 642
  • 775
  • Yes, I want to create a new local branch with name is same with remote branch to check out it. I will try Branch.lookup() as you recommend. – cauchuyennhocuatoi Mar 09 '21 at 07:16