git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Q: how can i find the upstream merge point of a commit?

From
Johan Herland <johan@herland.net>
Date
Jun 14, 2011, 23:45 UTC
Message-ID
<201106150145.12912.johan@herland.net>
In-Reply-To
<20110614171204.GC26764@sigill.intra.peff.net>
On Tuesday 14 June 2011, Jeff King wrote:
Show 22 quoted lines
> On Tue, Jun 14, 2011 at 11:56:56AM +0200, Johan Herland wrote:
> > 2. Interpreting/DWIMing refs
> > 
> > Changing the ref mappings require a revised set of rules for
> > interpreting shorthand ref names (expanding them into full ref names),
> > and handling ambiguities when they arise:
> > [...]
> > 
> > - "origin/foo" must continue to work, even if "refs/remotes/origin/foo"
> > has now become "refs/remotes/origin/heads/foo". In other words,
> > "foo/bar" where "foo" is a valid remote, must try to resolve "bar"
> > against the refspecs specified for the "foo" remote.
> 
> What happens if I ask for foo/bar/baz? Should it try to resolve:
> 
>   1. refs/remotes/foo/heads/bar/baz
> 
> or
> 
>   2. refs/remotes/foo/bar/heads/baz
> 
> or both (and if both, in which order)?

I think we want to do both, following these pseudo-bash steps (or something similar):

  shorthand=$1  # e.g. "foo/bar/baz"
  for remote in $(git remote)
  do
      case $shorthand in
        "$remote/"*)
          # Found matching remote
          trailer=${shorthand#$remote/}
          # Assert $remote/$trailer == $shorthand
          # DWIM $trailer into
          # - refs/heads/$trailer
          # - refs/tags/$trailer
          # etc.
          for dwimmed_ref in dwim_ref($trailer)
          do
              # Map $dwimmed_ref through refspec to get
              # remote-tracking ref, e.g. mapping
              # "refs/heads/spam" to "refs/remotes/$remote/heads/spam"
              remote_ref=map_through_refspec($dwimmed_ref, $remote)
              if test -n "$remote_ref"
              then
                  # Add $remote_ref to list of candidates
              fi
          done
          ;;
        *)
          # Non-match, ignore
          ;;
      esac
  done
  # We now have a list of (fully qualified) ref candidates
  # for $shorthand.
  # If there are zero candidates, there is no match for $shorthand.
  # If there is only one candidate, we have found an unambiguous
  # match for $shorthand.
  # If our current context demands a SHA1 object name, and all
  # candidates point to the same SHA1, there is no ambiguity.
  # Otherwise, $shorthand is ambiguous.

Using the above (pseudo)code, and assuming remotes "foo" and "foo/bar" exist (with remote branches "bar/baz" and "baz", respectively, and default new- style refspecs), then the "foo/bar/baz" shorthand would resolve to the following two remote-tracking branches:

- refs/remotes/foo/heads/bar/baz
- refs/remotes/foo/bar/heads/baz

This would likely result in an "ambiguous shorthand" error, unless the current context wants a SHA1 object name, and the two remote-tracking refs happen to point to the same SHA1 (in which case the result is unambiguous).

(Obviously, all of the above assumes that "foo/bar/baz" does not match any local ref, which would take precedence over the remote-tracking refs listed above.)

> I don't know offhand if "git remote" and "git clone" allow slashes in
> remote names, but I don't think we forbid it if somebody configures it
> themselves (and of course, remote names aside, they are free to write
> whatever refspecs they like in the config file).
  git remote add foo/bar .
does not report any errors for me.
Show 22 quoted lines
> > - If "refs/tags/foo" does not exist, tag name "foo" is unambiguous if
> > it exists in one or more "refs/remotes/*/tags/foo" and they all point
> > to the same SHA1.
> > 
> > - If "refs/tags/foo" does not exist, and more than one
> > "refs/remotes/*/tags/foo" exist, and they do NOT all point to the same
> > SHA1, then there is an ambiguity.
> > 
> > - The user may resolve the ambiguity by creating "refs/tags/foo"
> > pointing to the chosen SHA1 ("refs/tags/foo" takes precedence over
> > "refs/remotes/*/tags/foo").
> > 
> > - The same rules apply to heads, notes, etc.
> 
> I'm not sure we need all of these rules for anything but tags. We
> already keep remote heads in a separate namespace, and we don't
> automagically look them up. And that's OK, because the way tags and
> heads work is fundamentally different. I can peek at your remote heads,
> but if I checkout or merge, I better make a local branch that matches
> your remote one.  Whereas with tags, I don't think that is the case.
> They're really a read-only thing, and you want them to stay in the
> remotes namespace.

I don't really have any strong opinions here. As long as the rules end up being fairly intuitive and usable in practice, I'm quite happy to let others decide on the details.

FWIW, if I run "git log some_topic" and "some_topic" only exists as a remote-tracking ref ("refs/remotes/origin/heads/some_topic"), I do think I would prefer git to DWIM it, instead of simply failing with:

  fatal: bad revision: some_topic

This would be somewhat in line with the DWIMing already performed by "git checkout some_topic".

Have fun! :)
...Johan
-- 
Johan Herland, <johan@herland.net>
www.herland.net
Previous: Jeff KingNext: Jeff King
Message 13 of 19 in “Q: how can i find the upstream merge point of a commit?”
  1. Ingo MolnarJun 8, 2011
  2. Johannes SixtJun 8, 2011
  3. Stephen RothwellJun 8, 2011
  4. Peter ZijlstraJun 8, 2011
  5. Stephen RothwellJun 8, 2011
  6. Peter ZijlstraJun 8, 2011
  7. Ingo MolnarJun 8, 2011
  8. Sverre RabbelierJun 8, 2011
  9. Ingo MolnarJun 8, 2011
  10. Nguyen Thai Ngoc DuyJun 8, 2011
  11. Johan HerlandJun 14, 2011
  12. Jeff KingJun 14, 2011
  13. Johan HerlandJun 14, 2011
  14. Jeff KingJun 15, 2011
  15. Junio C HamanoJun 15, 2011
  16. Jeff KingJun 16, 2011
  17. Jakub NarebskiJun 16, 2011
  18. Junio C HamanoJun 8, 2011
  19. Ingo MolnarJun 8, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.