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

Re: [RFC/PATCH] tag: make list exclude !<pattern>

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Feb 13, 2012, 09:37 UTC
Message-ID
<4F38D9D4.5000203@alum.mit.edu>
In-Reply-To
<7vsjifgrwl.fsf@alter.siamese.dyndns.org>
On 02/13/2012 07:37 AM, Junio C Hamano wrote:
Show 13 quoted lines
> Michael Haggerty <mhagger@alum.mit.edu> writes:
> 
>> Of *course* they operate on different namespaces.  But part of the way
>> that revisions are selected using rev-list is by *selecting or excluding
>> refnames* from which it should crawl.
> 
> I am appalled if that is truly the understanding of yours, after having
> taken more than a few patches from you to fairly core parts of Git.
> 
> "rev-list A ^B" does not say "include A and exclude B from which rev-list
> should crawl" AT ALL.  We _actively_ crawl from both A and B.  It is that
> what are reachable from B is painted in a color different from the color
> in which we paint what are reachable from A.
Please read my emails more carefully before insulting me.

It is perfectly clear to me that there are two types of exclusion that we are talking about. And *both* of them are (or should be) relevant to rev-parse.

Take the following repository with three branches:
o---o---o---o  A
     \   \
      \   o---o  C
       \
        o---o  B

If I do "git rev-list A B ^C" then I get the commits marked "*" in the following diagram

o---o---o---*  A
     \   \
      \   o---o  C
       \
        *---*  B
By excluding C I have necessarily excluded a part of the history of A and B.

If we assume that the proposed feature is implemented and I do "git rev-list $(git for-each-ref --format='%(refname)' A B ^C)", then I get something different:

*---*---*---*  A
     \   \
      \   o---o  C
       \
        *---*  B

I argue that this is a useful selection. For example, maybe I want to remove the clutter of branch C from my view, but I still want to see the *whole* history of branches A and B. The middle selection doesn't do it.

Obviously this is not really necessary if there are only three branches, but if there are dozens, and if A, B, and C are patterns rather than literal branch names, then it can be very convenient.

For example, suppose I want to see the status of all of my submissions in your repository in the context of your main branches plus my local branches. It would be great to be able to type

    gitk --with-branch='refs/heads/*' \
         --with-branch='remotes/gitster/*' \
         --without-branch='remotes/gitster/*/**' \
         --with-branch='remotes/gitster/mh/*'
I don't know of a way to do that now.
Show 12 quoted lines
> A better pair you could have mentioned would be for-each-ref vs rev-parse
> (not rev-list).  What Tom wanted with "do not show the refs that match the
> pattern" he originally wanted to give to "tag --list" would be
> 
> 	for-each-ref A ^B
> 
> that is "show ref that matches A but do not show if it also matches B",
> while what you want to say is "I want to paint A in positive color and
> paint B in negative color, and I want to get a canonical notation to do
> so", it is spelled with rev-parse, not for-each-ref, like this:
> 
> 	rev-parse A ^B
That's not what I want; see above.
Show 12 quoted lines
> In other words,
> 
> 	git rev-list $(git rev-parse A ^B)
> 
> would be the equivalent to "git rev-list A ^B".
> 
> Maybe you are troubled that there are multiple concepts of negation, which
> ultimately comes from the undeniable fact that for-each-ref and rev-parse
> operate on entities in different concept domain (refnames and objects)?
> And if we decide to use "^", then these two different concepts of negation
> are both expressed with the same operator "prefix ^", leading to
> confusion?

Not only that, but also that both concepts of negation are interesting and useful within "git rev-list", and therefore we should make them *combinable*.

To be very explicit, I advocate:
1. Implement an explicit syntax for "do not include references matching
this pattern in a list of references".  Implement this syntax in
for-each-ref; something like
    --with-ref=PATTERN / --without-ref=PATTERN
    --with-branch=PATTERN / --without-branch=PATTERN
    --with-tag=PATTERN / --without-tag=PATTERN
    --with-remote=PATTERN / --without-remote=PATTERN

The point of having multiple with/without pairs would be that the first would match full refnames explicitly (i.e., the pattern would usually start with "refs/"), whereas the other pairs would implicitly prepend "refs/heads/", "refs/tags/", or "refs/remotes/", respectively, to the pattern for convenience. There should also be an "--all" option that is equivalent to "--with-ref=**".

The output from for-each-ref would essentially be a *list of positive references* matching the criteria. In other words, "--without-branch=foo" would cause "refs/heads/foo" to be *excluded* from the output altogether, *not* included as "^refs/heads/foo".

The order of the options should be significant, with the last matching pattern winning.

2. The pattern matching of refnames should be like fnmatch, with the
addition of "**" as a wildcard meaning "any characters, including '/'".
3. Other reference-listing commands should take the same options as
appropriate; for example, "git branch --list" would take
--with(out)?-branch and --with(out)?-remote (and maybe
--with(out)?-ref); "git tag --list" would take --with(out)?-tag (and
maybe --with(out)?-ref), etc.
4. The *exact same options* should be added to rev-list, and would
effectively be expanded into a list of positive references; e.g.,
    git rev-list --with-branch=A --with-branch=B --without-branch=C
would be equivalent to
    git rev-list $(git for-each-ref --format='%(refname)'
--with-branch=A --with-branch=B --without-branch=C)

If A, B, and C happen to be branch names rather than patterns, the above would be equivalent to

    git rev-list refs/heads/A refs/heads/B
Note that this *differs* (in a useful way!) from
    git rev-list refs/heads/A refs/heads/B --not refs/heads/C
or
    git rev-list refs/heads/A refs/heads/B ^refs/heads/C

which are useful in other scenarios and whose meanings we would of course retain.

If "--not" is used in git-rev-list, it would demarcate groups of options that are passed separately to for-each-ref; for example,

    git rev-list --all --with-branch=A --without-branch=B \
           --not --with-branch=C --without-branch=D
would be equivalent to
    git rev-list $(git for-each-ref --format='%(refname)' --all
--with-branch=A --without-branch=B)\
           --not $(git for-each-ref --format='%(refname)'
--with-branch=C --without-branch=D)
Michael
-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
Previous: Junio C HamanoNext: Junio C Hamano
Message 29 of 83 in “tag: make list exclude !<pattern>”
  1. tag: make list exclude !<pattern>Tom Grennan, Feb 9, 2012
  2. tag: make list exclude !<pattern>Tom Grennan, Feb 9, 2012
  3. Tom GrennanFeb 10, 2012
  4. Nguyen Thai Ngoc DuyFeb 10, 2012
  5. Tom GrennanFeb 10, 2012
  6. Tom GrennanFeb 11, 2012
  7. 1/4 refs: add common refname_match_patterns()Tom Grennan, Feb 11, 2012
  8. Michael HaggertyFeb 11, 2012
  9. Tom GrennanFeb 11, 2012
  10. Michael HaggertyFeb 13, 2012
  11. Tom GrennanFeb 13, 2012
  12. Junio C HamanoFeb 11, 2012
  13. Tom GrennanFeb 11, 2012
  14. Junio C HamanoFeb 11, 2012
  15. Tom GrennanFeb 13, 2012
  16. 2/4 tag: use refs.c:refname_match_patterns()Tom Grennan, Feb 11, 2012
  17. 3/4 branch: use refs.c:refname_match_patterns()Tom Grennan, Feb 11, 2012
  18. 4/4 for-each-ref: use refs.c:refname_match_patterns()Tom Grennan, Feb 11, 2012
  19. Junio C HamanoFeb 11, 2012
  20. Junio C HamanoFeb 11, 2012
  21. Jakub NarebskiFeb 11, 2012
  22. Nguyen Thai Ngoc DuyFeb 11, 2012
  23. Junio C HamanoFeb 11, 2012
  24. Tom GrennanFeb 11, 2012
  25. Michael HaggertyFeb 11, 2012
  26. Junio C HamanoFeb 11, 2012
  27. Michael HaggertyFeb 13, 2012
  28. Junio C HamanoFeb 13, 2012
  29. Michael HaggertyFeb 13, 2012
  30. Junio C HamanoFeb 13, 2012
  31. Michael HaggertyFeb 13, 2012
  32. Junio C HamanoFeb 13, 2012
  33. Tom GrennanFeb 11, 2012
  34. 0/5 Re: tag: make list exclude !<pattern>Tom Grennan, Feb 22, 2012
  35. 1/5 refs: add match_pattern()Tom Grennan, Feb 22, 2012
  36. Junio C HamanoFeb 22, 2012
  37. Tom GrennanFeb 22, 2012
  38. Junio C HamanoFeb 23, 2012
  39. Tom GrennanFeb 23, 2012
  40. 2/5 tag --points-at option wrapperTom Grennan, Feb 22, 2012
  41. 3/5 tag --exclude optionTom Grennan, Feb 22, 2012
  42. Junio C HamanoFeb 22, 2012
  43. Tom GrennanFeb 23, 2012
  44. Junio C HamanoFeb 23, 2012
  45. 0/5 modernize test styleTom Grennan, Mar 1, 2012
  46. 1/5 t6300 (for-each-ref): modernize styleTom Grennan, Mar 1, 2012
  47. Johannes SixtMar 1, 2012
  48. Tom GrennanMar 1, 2012
  49. 2/5 t5512 (ls-remote): modernize styleTom Grennan, Mar 1, 2012
  50. Thomas RastMar 1, 2012
  51. 3/5 t3200 (branch): modernize styleTom Grennan, Mar 1, 2012
  52. 4/5 t0040 (parse-options): modernize styleTom Grennan, Mar 1, 2012
  53. 5/5 t7004 (tag): modernize styleTom Grennan, Mar 1, 2012
  54. 101/105 t6300 (for-each-ref): modernize styleTom Grennan, Mar 1, 2012
  55. Junio C HamanoMar 1, 2012
  56. Tom GrennanMar 1, 2012
  57. Junio C HamanoMar 1, 2012
  58. Tom GrennanMar 1, 2012
  59. Tom GrennanMar 1, 2012
  60. Thomas RastMar 1, 2012
  61. Tom GrennanMar 1, 2012
  62. 102/105 t5512 (ls-remote): modernize styleTom Grennan, Mar 1, 2012
  63. 103/105 t3200 (branch): modernize styleTom Grennan, Mar 1, 2012
  64. 104/105 t0040 (parse-options): modernize styleTom Grennan, Mar 1, 2012
  65. 105/105 t7004 (tag): modernize styleTom Grennan, Mar 1, 2012
  66. 0/5 modernize test styleTom Grennan, Mar 3, 2012
  67. 1/5 t7004 (tag): modernize styleTom Grennan, Mar 3, 2012
  68. Johannes SixtMar 3, 2012
  69. 2/5 t5512 (ls-remote): modernize styleTom Grennan, Mar 3, 2012
  70. Junio C HamanoMar 3, 2012
  71. Tom GrennanMar 3, 2012
  72. 3/5 t3200 (branch): modernize styleTom Grennan, Mar 3, 2012
  73. 4/5 t0040 (parse-options): modernize styleTom Grennan, Mar 3, 2012
  74. 5/5 t6300 (for-each-ref): modernize styleTom Grennan, Mar 3, 2012
  75. 101/105 t7004 (tag): modernize styleTom Grennan, Mar 3, 2012
  76. 102/105 t5512 (ls-remote): modernize styleTom Grennan, Mar 3, 2012
  77. 103/105 t3200 (branch): modernize styleTom Grennan, Mar 3, 2012
  78. 104/105 t0040 (parse-options): modernize styleTom Grennan, Mar 3, 2012
  79. 105/105 t6300 (for-each-ref): modernize styleTom Grennan, Mar 3, 2012
  80. Junio C HamanoMar 3, 2012
  81. Tom GrennanMar 3, 2012
  82. 4/5 branch --exclude optionTom Grennan, Feb 22, 2012
  83. 5/5 for-each-ref --exclude optionTom Grennan, Feb 22, 2012

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.