0

When I run a git clone to set up a new repo with a remote, I end up with origin/HEAD that I can use to identify the head of the default branch on origin without having to first know what the owner of the remote happens to have named it (I've seen both origin and master and occupationally both in the same remote).

However if I then add a new remote via git remote add foo ... the new remote doesn't have a foo/HEAD, so any attempt to use that to look up the remote's default branch will fail.

Other than manually looking up the default branch for each new remote and adding ${REMOTE}/HEAD, (and hoping the default branch isn't changed at some later point) is there any way to programmatic find the default branch for a given remote?

(FWIW: I'm using GitPython.)

BCS
  • 75,627
  • 68
  • 187
  • 294
  • The docs is very clear about it: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-headem – phd May 19 '21 at 21:22
  • @phd: The linked docs describe a CLI command that is the functional equivalent of the manual lookup I already mentioned with all it's disadvantages (it's a mutating operation, it doesn't track changes in the remote default, etc.). What I want, is a way for my GitPython code to do the query that the `--auto` flags speaks of rather than depend on it having already been done. – BCS May 19 '21 at 23:09
  • 1
    If a repository does not have a `HEAD`, it does not have a default branch at all. The branch name stored in `HEAD` is the default branch. However, if a repository does not have a `HEAD`, it is not even a repository: Git will refuse to use a `.git` directory that is missing a `HEAD` file. So this case never actually happens anyway. – torek May 20 '21 at 06:07
  • 1
    If your issue is that `git remote add` does not create the `HEAD` entry, that part is easy to solve: run `git remote set-head` after `git remote add`, so that your Git calls up that Git and queries its `HEAD` setting. (Use `--auto` here.) There is a potential flaw if the server is ancient (or if your client is ancient, but you can fix that one) since ancient Gits do not have the ability to report a *symbolic* HEAD and hence must guess based on actual branch names and hash IDs, which does not work until the actual branch name itself has an associated hash ID. – torek May 20 '21 at 06:09
  • 2
    If your issue is that the `HEAD` setting may be out of date, well, that's *always* a danger. The only way to get an updated entry is to run `set-head` again. Git probably ought to expose the symbolic head setting more directly (through `git ls-remote` for instance). It sort of does, in modern Git, with `git ls-remote --symref`, but as with the set-head issues with older servers, it isn't entirely reliable. It might be good enough for whatever you're doing though. – torek May 20 '21 at 06:10
  • @torek : hmmm ... there still isn't that "promote to answer" button :) – LeGEC May 20 '21 at 06:54
  • @torek: I may be using terminology incorrectly so don't read too much into that. -- As for the rest of your comments: yes, I'm worried about the default branch having changed between now and when I ran `clone`. I'm also wanting a solution that doesn't *require* write access to the local repo, which kills options like `git remote set-head`. In effect I want to lookup the data that `set-head --auto` would use but then not modify anything. -- And old servers are not a major concern. – BCS May 20 '21 at 18:44
  • What sort of project changes its default branch name (let alone history) without a big fat notice on the issues/mailing list or whatever sideband channel they use? Any crew going to omit that, I'm thinking that'll be likely enough the least of your troubles. Still, `git ls-remote --symref u://r/l HEAD` does what you want, it doesn't even require a local repo at all, let alone write access to one, or you can init a repo on a tmpfs and do the set-head --auto there, there's no magic to this. – jthill May 20 '21 at 19:03
  • Most automation tools don't subscribe to mailing-lists and I'm not willing to assume that the user is subscribed for every project they check out, nor that they remember to update things. The primary point of what I'm working on is reporting to you those things you forgot to do, so "the user is unreliable" is my assumed baseline. -- From that, it looks like the best I can do is have GitPython shell out and parse the result `repo.git.execute(["git", "ls-remote", "--symref", repo.remotes[0].url, "HEAD"])` ... yuck. – BCS May 20 '21 at 19:40

0 Answers0