diff mbox series

[bug#49252] Channels defaulting to HEAD instead of ‘master’

Message ID 87y2auw3jo.fsf@inria.fr
State New
Headers show
Series [bug#49252] Channels defaulting to HEAD instead of ‘master’ | expand

Commit Message

Ludovic Courtès June 28, 2021, 12:56 p.m. UTC
Hi,

With an eye on allowing channel authors, and Guix in particular, to
eventually be able to choose a default branch name other than ‘master’,
what about changing defaults like this:
For the record, commit cb41c15827a2e910aa56fb5d1917ba8a085c95c7 by Kyle
(Cc’d) gives the ability to use the remote HEAD by default, which is
exactly what we need here.

Unfortunately, for the Guix repo at Savannah, I get:

--8<---------------cut here---------------start------------->8---
$ ./pre-inst-env guix time-machine -- describe
guix time-machine: error: Git error: reference 'refs/remotes/origin/HEAD' not found
--8<---------------cut here---------------end--------------->8---

… but it works for <https://github.com/guix-mirror/guix>.

Presumably we have a server-side setup issue at Savannah?

Are there downsides, or cases where it might pick the wrong branch?

Thoughts?

Ludo’.

Comments

Kyle Meyer July 9, 2021, 12:38 a.m. UTC | #1
Ludovic Courtès writes:

> For the record, commit cb41c15827a2e910aa56fb5d1917ba8a085c95c7 by Kyle
> (Cc’d) gives the ability to use the remote HEAD by default, which is
> exactly what we need here.
>
> Unfortunately, for the Guix repo at Savannah, I get:
>
> --8<---------------cut here---------------start------------->8---
> $ ./pre-inst-env guix time-machine -- describe
> guix time-machine: error: Git error: reference 'refs/remotes/origin/HEAD' not found
> --8<---------------cut here---------------end--------------->8---
>
> … but it works for <https://github.com/guix-mirror/guix>.
>
> Presumably we have a server-side setup issue at Savannah?

Hmm, it looks like it's there:

  $ git ls-remote https://git.savannah.gnu.org/git/guix.git | grep HEAD
  e499500730de23fd54ae63696a725d4b90a406d7	HEAD

  $ git clone https://git.savannah.gnu.org/git/guix.git && cd guix
  $ git for-each-ref refs/remotes/origin | grep HEAD
  e499500730de23fd54ae63696a725d4b90a406d7 commit	refs/remotes/origin/HEAD
  $ git name-rev refs/remotes/origin/HEAD
  refs/remotes/origin/HEAD master

This might be a long shot, but if you cloned the repo with magit-clone,
it has some custom logic that deletes refs/remotes/<remote>/HEAD unless
magit-clone-set-remote-head is non-nil (and it's nil by default).

> Are there downsides, or cases where it might pick the wrong branch?

The main downside I can think of is what I mentioned in bug#45187
(87v9d8dk0r.fsf@kyleam.com):

  [The remote HEAD symref] probably the best indicator of what the
  primary branch is.  In a clone, it doesn't necessarily match HEAD on
  the remote, because users may change it to another branch they're
  interested in, but that isn't really relevant to these
  behind-the-scenes checkouts.

So, if it's a user-facing clone, refs/remotes/origin/HEAD isn't a
reliable indicator because users are free to redirect the remote HEAD
symref to another branch of interest [*] or to delete it altogether.

I think channel clones would fall into the "behind the scenes" category,
though, right?


[*] This is discussed here:
    https://lore.kernel.org/git/xmqqlfivwvtw.fsf@gitster.c.googlers.com/
Ludovic Courtès Aug. 4, 2021, 3:04 p.m. UTC | #2
Hi Kyle,

Kyle Meyer <kyle@kyleam.com> skribis:

> Ludovic Courtès writes:
>
>> For the record, commit cb41c15827a2e910aa56fb5d1917ba8a085c95c7 by Kyle
>> (Cc’d) gives the ability to use the remote HEAD by default, which is
>> exactly what we need here.
>>
>> Unfortunately, for the Guix repo at Savannah, I get:
>>
>> --8<---------------cut here---------------start------------->8---
>> $ ./pre-inst-env guix time-machine -- describe
>> guix time-machine: error: Git error: reference 'refs/remotes/origin/HEAD' not found
>> --8<---------------cut here---------------end--------------->8---
>>
>> … but it works for <https://github.com/guix-mirror/guix>.
>>
>> Presumably we have a server-side setup issue at Savannah?
>
> Hmm, it looks like it's there:
>
>   $ git ls-remote https://git.savannah.gnu.org/git/guix.git | grep HEAD
>   e499500730de23fd54ae63696a725d4b90a406d7	HEAD
>
>   $ git clone https://git.savannah.gnu.org/git/guix.git && cd guix
>   $ git for-each-ref refs/remotes/origin | grep HEAD
>   e499500730de23fd54ae63696a725d4b90a406d7 commit	refs/remotes/origin/HEAD
>   $ git name-rev refs/remotes/origin/HEAD
>   refs/remotes/origin/HEAD master

OK, so something else must be at fault.

Ideas?

> This might be a long shot, but if you cloned the repo with magit-clone,
> it has some custom logic that deletes refs/remotes/<remote>/HEAD unless
> magit-clone-set-remote-head is non-nil (and it's nil by default).

No, these are clones managed via (guix git) only.

>> Are there downsides, or cases where it might pick the wrong branch?
>
> The main downside I can think of is what I mentioned in bug#45187
> (87v9d8dk0r.fsf@kyleam.com):
>
>   [The remote HEAD symref] probably the best indicator of what the
>   primary branch is.  In a clone, it doesn't necessarily match HEAD on
>   the remote, because users may change it to another branch they're
>   interested in, but that isn't really relevant to these
>   behind-the-scenes checkouts.
>
> So, if it's a user-facing clone, refs/remotes/origin/HEAD isn't a
> reliable indicator because users are free to redirect the remote HEAD
> symref to another branch of interest [*] or to delete it altogether.
>
> I think channel clones would fall into the "behind the scenes" category,
> though, right?

Right, those cached clones managed by (guix git) are behind the scenes;
we can assume only (guix git) will only ever touch them.

Thanks,
Ludo’.
Ricardo Wurmus Aug. 8, 2021, 1:53 p.m. UTC | #3
Ludovic Courtès <ludo@gnu.org> writes:

> For the record, commit cb41c15827a2e910aa56fb5d1917ba8a085c95c7 
> by Kyle
> (Cc’d) gives the ability to use the remote HEAD by default, 
> which is
> exactly what we need here.
>
> Unfortunately, for the Guix repo at Savannah, I get:
>
> --8<---------------cut 
> here---------------start------------->8---
> $ ./pre-inst-env guix time-machine -- describe
> guix time-machine: error: Git error: reference 
> 'refs/remotes/origin/HEAD' not found
> --8<---------------cut 
> here---------------end--------------->8---
>
> … but it works for <https://github.com/guix-mirror/guix>.

For what it’s worth I found the same kind of problem when 
importing an R package from Github:

   ./pre-inst-env guix import cran -a git 
   https://github.com/ImmuneDynamics/Spectre

Here’s the error backtrace:

--8<---------------cut here---------------start------------->8---
Backtrace:
In ice-9/boot-9.scm:
    724:2 19 (call-with-prompt _ _ #<procedure 
    default-prompt-handler (k proc)>)
In ice-9/eval.scm:
    619:8 18 (_ #(#(#<directory (guile-user) 7f95f8626c80>)))
In guix/ui.scm:
   2185:7 17 (run-guix . _)
  2148:10 16 (run-guix-command _ . _)
In guix/scripts/import.scm:
   120:11 15 (guix-import . _)
In guix/scripts/import/cran.scm:
   110:25 14 (guix-import-cran . _)
In guix/memoization.scm:
     98:0 13 (mproc "https://github.com/ImmuneDynamics/Spectre" 
     #:repo git)
In unknown file:
          12 (_ #<procedure 7f95f4ce5e60 at 
          guix/memoization.scm:179:32 ()> #<procedure list _> 
          (this is nothing))
In guix/import/cran.scm:
   594:24 11 (_ "https://github.com/ImmuneDynamics/Spectre" #:repo 
   _ #:version _)
   279:25 10 (fetch-description _ 
   "https://github.com/ImmuneDynamics/Spectre")
In guix/memoization.scm:
     98:0  9 (mproc "https://github.com/ImmuneDynamics/Spectre" 
     #:method git)
In unknown file:
           8 (_ #<procedure 7f95f4ce5e00 at 
           guix/memoization.scm:179:32 ()> #<procedure list _> 
           (this is nothing))
In ice-9/boot-9.scm:
  1752:10  7 (with-exception-handler _ _ #:unwind? _ 
  #:unwind-for-type _)
In guix/store.scm:
   658:37  6 (thunk)
In guix/git.scm:
    481:8  5 (latest-repository-commit #<store-connection 256.99 
    7f95f4c18320> "https://github.com/ImmuneDynamics/Spectre" 
    #:recursive? _ #:log-port _ #:cache-directory _ #:ref _)
    247:4  4 (update-cached-checkout _ #:ref _ #:recursive? _ 
    #:check-out? _ #:starting-commit _ #:log-port _ 
    #:cache-directory _)
   214:18  3 (resolve _)
In git/reference.scm:
     60:8  2 (_ _ _)
In git/bindings.scm:
     77:2  1 (raise-git-error _)
In ice-9/boot-9.scm:
  1685:16  0 (raise-exception _ #:continuable? _)

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Git error: reference 'refs/remotes/origin/HEAD' not found
--8<---------------cut here---------------end--------------->8---

> Presumably we have a server-side setup issue at Savannah?

I think it might be a repository setting rather than a server 
setting as other Github repositories work, yet this one repo on 
Github does not.
Kyle Meyer Aug. 8, 2021, 11:08 p.m. UTC | #4
Ricardo Wurmus writes:

> For what it’s worth I found the same kind of problem when 
> importing an R package from Github:
>
>    ./pre-inst-env guix import cran -a git 
>    https://github.com/ImmuneDynamics/Spectre
>
> Here’s the error backtrace:
[...]
>
> ice-9/boot-9.scm:1685:16: In procedure raise-exception:
> Git error: reference 'refs/remotes/origin/HEAD' not found
> --8<---------------cut here---------------end--------------->8---
>
>> Presumably we have a server-side setup issue at Savannah?
>
> I think it might be a repository setting rather than a server 
> setting as other Github repositories work, yet this one repo on 
> Github does not.

Hmm, I'm not sure what's going on here, but, as with
<https://git.savannah.gnu.org/git/guix.git>, if I clone the above repo
via `git clone', refs/remotes/origin/HEAD is there:

  $ git ls-remote https://github.com/ImmuneDynamics/Spectre | grep HEAD
  742ebc4bc09ce69b970eceb78291bdbf5229d20d	HEAD

  $ git clone https://github.com/ImmuneDynamics/Spectre && cd Spectre
  $ git for-each-ref refs/remotes/origin | grep HEAD
  742ebc4bc09ce69b970eceb78291bdbf5229d20d commit	refs/remotes/origin/HEAD
Kyle Meyer Aug. 8, 2021, 11:28 p.m. UTC | #5
Ludovic Courtès writes:

> Kyle Meyer <kyle@kyleam.com> skribis:
[...]
>>
>> Hmm, it looks like it's there:
>>
>>   $ git ls-remote https://git.savannah.gnu.org/git/guix.git | grep HEAD
>>   e499500730de23fd54ae63696a725d4b90a406d7	HEAD
>>
>>   $ git clone https://git.savannah.gnu.org/git/guix.git && cd guix
>>   $ git for-each-ref refs/remotes/origin | grep HEAD
>>   e499500730de23fd54ae63696a725d4b90a406d7 commit	refs/remotes/origin/HEAD
>>   $ git name-rev refs/remotes/origin/HEAD
>>   refs/remotes/origin/HEAD master
>
> OK, so something else must be at fault.
>
> Ideas?

My understanding is that the clone is happening through guile-git, which
uses libgit2.  In libgit2's v1.1.0 release notes, I see "[t]he
refs/remotes/origin/HEAD file will be created at clone time to point to
the origin's default branch".  So my current guess is that this clone
was made before guix's libgit2 was 1.1.0.

Does that sound possible (i.e. this clone is from before 2020-12-ish)?
Do you still see the "reference 'refs/remotes/origin/HEAD' not found"
failure if you force a fresh clone?
Ludovic Courtès Aug. 9, 2021, 9:12 a.m. UTC | #6
Hello Kyle,

Kyle Meyer <kyle@kyleam.com> skribis:

> Ludovic Courtès writes:
>
>> Kyle Meyer <kyle@kyleam.com> skribis:
> [...]
>>>
>>> Hmm, it looks like it's there:
>>>
>>>   $ git ls-remote https://git.savannah.gnu.org/git/guix.git | grep HEAD
>>>   e499500730de23fd54ae63696a725d4b90a406d7	HEAD
>>>
>>>   $ git clone https://git.savannah.gnu.org/git/guix.git && cd guix
>>>   $ git for-each-ref refs/remotes/origin | grep HEAD
>>>   e499500730de23fd54ae63696a725d4b90a406d7 commit	refs/remotes/origin/HEAD
>>>   $ git name-rev refs/remotes/origin/HEAD
>>>   refs/remotes/origin/HEAD master
>>
>> OK, so something else must be at fault.
>>
>> Ideas?
>
> My understanding is that the clone is happening through guile-git, which
> uses libgit2.  In libgit2's v1.1.0 release notes, I see "[t]he
> refs/remotes/origin/HEAD file will be created at clone time to point to
> the origin's default branch".  So my current guess is that this clone
> was made before guix's libgit2 was 1.1.0.
>
> Does that sound possible (i.e. this clone is from before 2020-12-ish)?
> Do you still see the "reference 'refs/remotes/origin/HEAD' not found"
> failure if you force a fresh clone?

Oh, this must be the reason.  If I remove the cached clone:

  rm -rf ~/.cache/guix/checkouts/pjmkglp4t7znuugeurpurzikxq3tnlaywmisyr27shj7apsnalwq

and then clone again, it works:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,use(guix git)
scheme@(guile-user)> (update-cached-checkout "https://git.savannah.gnu.org/git/guix.git")
$2 = "/home/ludo/.cache/guix/checkouts/pjmkglp4t7znuugeurpurzikxq3tnlaywmisyr27shj7apsnalwq"
$3 = "30289f4d4638452520f52c1a36240220d0d940ff"
$4 = #f
--8<---------------cut here---------------end--------------->8---

Likewise with the other repo Ricardo mentions:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (update-cached-checkout "https://github.com/ImmuneDynamics/Spectre")
$5 = "/home/ludo/.cache/guix/checkouts/lpz4iyuu3pztx73ks74bfiymewyzn24rm565l6cgiutvjow5joka"
$6 = "742ebc4bc09ce69b970eceb78291bdbf5229d20d"
$7 = #f
--8<---------------cut here---------------end--------------->8---

I suppose we need to add a call to fetch remote heads when they’re
missing?  It seems that calling ‘remote-fetch’ is not enough.  If I
explicitly remove ‘HEAD’ from the clone, then I get:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (define r (repository-open "/home/ludo/.cache/guix/checkouts/lpz4iyuu3pztx73ks74bfiymewyzn24rm565l6cgiutvjow5joka"))
scheme@(guile-user)> (reference-name->oid r "refs/remotes/origin/HEAD")
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Git error: reference 'refs/remotes/origin/HEAD' not found


Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,q
scheme@(guile-user)> (remote-fetch (remote-lookup r "origin"))
scheme@(guile-user)> (reference-name->oid r "refs/remotes/origin/HEAD")
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Git error: reference 'refs/remotes/origin/HEAD' not found


Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,q
--8<---------------cut here---------------end--------------->8---

Calling ‘remote-ls’ doesn’t populate that file either:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (define o (remote-lookup r "origin"))
scheme@(guile-user)> (remote-connect o)
scheme@(guile-user)> (remote-ls o)
$13 = (#<<remote-head> local: 0 oid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> loid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> name: "HEAD" symref-target: 73408368> #<<remote-head> local: 0 oid: #<oid 00000000c9d6e28e5d48c056ee6ad36cc4ab0861> loid: #<oid 00000000c9d6e28e5d48c056ee6ad36cc4ab0861> name: "refs/heads/development" symref-target: 0> #<<remote-head> local: 0 oid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> loid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> name: "refs/heads/master" symref-target: 0> #<<remote-head> local: 0 oid: #<oid 00000000e6985cce0e75b63dab3032ae875f5592> loid: #<oid 00000000e6985cce0e75b63dab3032ae875f5592> name: "refs/heads/pre-release" symref-target: 0> […])
--8<---------------cut here---------------end--------------->8---

So I’m not sure what the best approach is.  Thoughts?

Ludo’.
Kyle Meyer Aug. 10, 2021, 2:10 a.m. UTC | #7
Ludovic Courtès writes:

> Oh, this must be the reason.  If I remove the cached clone:
>
>   rm -rf ~/.cache/guix/checkouts/pjmkglp4t7znuugeurpurzikxq3tnlaywmisyr27shj7apsnalwq
>
> and then clone again, it works:

Great, glad that that mystery is solved.

> I suppose we need to add a call to fetch remote heads when they’re
> missing?  It seems that calling ‘remote-fetch’ is not enough.

Right, a fetch won't do it [1].  Users are free to delete or redirect
refs/remotes/<remote>/HEAD, and a fetch won't repopulate it.

On the command line, you can query the remote and recreate the symref
with `remote set-head <remote> -a':

  $ git symbolic-ref -d refs/remotes/origin/HEAD
  $ git symbolic-ref refs/remotes/origin/HEAD
  fatal: ref refs/remotes/origin/HEAD is not a symbolic ref
  $ git remote set-head origin -a
  origin/HEAD set to master
  $ git symbolic-ref refs/remotes/origin/HEAD
  refs/remotes/origin/master

In the libgit2 world, I think the most direct path might be something
along the lines of "get remote ref via git_remote_default_branch()"
followed by "create refs/remotes/<remote>/HEAD via
git_reference_symbolic_create()".  I'm not spotting either of those
functions in guile-git, though.

I haven't confirmed but based on the "symref-target" in the remote-ls
output you showed...

> --8<---------------cut here---------------start------------->8---
> scheme@(guile-user)> (define o (remote-lookup r "origin"))
> scheme@(guile-user)> (remote-connect o)
> scheme@(guile-user)> (remote-ls o)
> $13 = (#<<remote-head> local: 0 oid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> loid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> name: "HEAD" symref-target: 73408368> [...]

... I guess it might be possible to determine the ref target with
remote-ls.  In that case, it'd just be the
git_reference_symbolic_create() wrapper that was missing.


[1] In addition to the link I gave upthread, see
    <https://lore.kernel.org/git/20180601065121.GA15578@sigill.intra.peff.net/>
    for some discussion about whether fetch should populate it.
Ludovic Courtès Aug. 10, 2021, 8:04 a.m. UTC | #8
Kyle Meyer <kyle@kyleam.com> skribis:

> Ludovic Courtès writes:
>
>> Oh, this must be the reason.  If I remove the cached clone:
>>
>>   rm -rf ~/.cache/guix/checkouts/pjmkglp4t7znuugeurpurzikxq3tnlaywmisyr27shj7apsnalwq
>>
>> and then clone again, it works:
>
> Great, glad that that mystery is solved.
>
>> I suppose we need to add a call to fetch remote heads when they’re
>> missing?  It seems that calling ‘remote-fetch’ is not enough.
>
> Right, a fetch won't do it [1].  Users are free to delete or redirect
> refs/remotes/<remote>/HEAD, and a fetch won't repopulate it.
>
> On the command line, you can query the remote and recreate the symref
> with `remote set-head <remote> -a':
>
>   $ git symbolic-ref -d refs/remotes/origin/HEAD
>   $ git symbolic-ref refs/remotes/origin/HEAD
>   fatal: ref refs/remotes/origin/HEAD is not a symbolic ref
>   $ git remote set-head origin -a
>   origin/HEAD set to master
>   $ git symbolic-ref refs/remotes/origin/HEAD
>   refs/remotes/origin/master
>
> In the libgit2 world, I think the most direct path might be something
> along the lines of "get remote ref via git_remote_default_branch()"
> followed by "create refs/remotes/<remote>/HEAD via
> git_reference_symbolic_create()".  I'm not spotting either of those
> functions in guile-git, though.
>
> I haven't confirmed but based on the "symref-target" in the remote-ls
> output you showed...
>
>> --8<---------------cut here---------------start------------->8---
>> scheme@(guile-user)> (define o (remote-lookup r "origin"))
>> scheme@(guile-user)> (remote-connect o)
>> scheme@(guile-user)> (remote-ls o)
>> $13 = (#<<remote-head> local: 0 oid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> loid: #<oid 00000000742ebc4bc09ce69b970eceb78291bdbf> name: "HEAD" symref-target: 73408368> [...]
>
> ... I guess it might be possible to determine the ref target with
> remote-ls.  In that case, it'd just be the
> git_reference_symbolic_create() wrapper that was missing.

Right.  We can add the missing procedures in Guile-Git, but in the
meantime, maybe we could create .git/refs/origin/HEAD “by hand”?  The
advantage is that we wouldn’t have to wait for the new Guile-Git
release; but OTOH, we’re the ones making the Guile-Git release, too…

Thanks,
Ludo’.
Kyle Meyer Aug. 11, 2021, 12:34 a.m. UTC | #9
Ludovic Courtès writes:

> Right.  We can add the missing procedures in Guile-Git, but in the
> meantime, maybe we could create .git/refs/origin/HEAD “by hand”?

Yep, for the default branch $NAME, "ref: refs/remotes/origin/$NAME\n"
can be written to .git/refs/origin/HEAD.

With respect to getting the default branch, I said in my last message
that I thought it'd be possible to glean the target from the remote-ls
output.  To flesh that out a bit:

--8<---------------cut here---------------start------------->8---
(use-modules
 (git)
 (system foreign))

(define origin (remote-lookup (repository-open ".") "origin"))
(remote-connect origin)

(define head (car (remote-ls origin)))

(define target-pt
  (make-pointer
   ((record-accessor (record-type-descriptor head) 'symref-target)
    head)))

(if (not (null-pointer? target-pt))
    (display (pointer->string target-pt)))  ;; => refs/heads/master
--8<---------------cut here---------------end--------------->8---

And that looks like it matches what libgit2's
git_remote_default_branch() does for the non-guessing case (see below),
so stopping there may be sufficient for a compatibility kludge.

--8<---------------cut here---------------start------------->8---
	if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0)
		goto done;

	if (heads_len == 0 || strcmp(heads[0]->name, GIT_HEAD_FILE)) {
		error = GIT_ENOTFOUND;
		goto done;
	}

	if ((error = git_buf_sanitize(out)) < 0)
		return error;

	/* the first one must be HEAD so if that has the symref info, we're done */
	if (heads[0]->symref_target) {
		error = git_buf_puts(out, heads[0]->symref_target);
		goto done;
	}

	/*
	 * If there's no symref information, we have to look over them
	 * and guess. We return the first match unless the default
	 * branch is a candidate. Then we return the default branch.
*/--8<---------------cut here---------------end--------------->8---
diff mbox series

Patch

diff --git a/guix/channels.scm b/guix/channels.scm
index 476d62e1f4..a5283b4bf4 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -122,7 +122,7 @@ 
   channel?
   (name      channel-name)
   (url       channel-url)
-  (branch    channel-branch (default "master"))
+  (branch    channel-branch (default #f))
   (commit    channel-commit (default #f))
   (introduction channel-introduction (default #f))
   (location  channel-location
@@ -179,7 +179,6 @@  to the corresponding bytevector."
 (define %default-guix-channel
   (channel
    (name 'guix)
-   (branch "master")
    (url %default-channel-url)
    (introduction %guix-channel-introduction)))
 
@@ -225,7 +224,9 @@  introduction, add it."
   "Return the \"reference\" for CHANNEL, an sexp suitable for
 'latest-repository-commit'."
   (match (channel-commit channel)
-    (#f      `(branch . ,(channel-branch channel)))
+    (#f      (if (channel-branch channel)
+                 `(branch . ,(channel-branch channel))
+                 '()))                            ;remote HEAD
     (commit  `(commit . ,(channel-commit channel)))))
 
 (define sexp->channel-introduction
diff --git a/guix/inferior.scm b/guix/inferior.scm
index 7c8e478f2a..3db63167fd 100644
--- a/guix/inferior.scm
+++ b/guix/inferior.scm
@@ -732,7 +732,10 @@  prefix, resolve it; and if 'commit' is unset, fetch CHANNEL's branch tip."
         (branch (channel-branch channel)))
     (if (and commit (= (string-length commit) 40))
         commit
-        (let* ((ref (if commit `(commit . ,commit) `(branch . ,branch)))
+        (let* ((ref (cond
+                     (commit `(commit . ,commit))
+                     (branch `(branch . ,branch))
+                     (else   '())))               ;remote HEAD
                (cache commit relation
                      (update-cached-checkout (channel-url channel)
                                              #:ref ref