# Re: [PATCH] Documentation: add a planning document for the next CLI revamp

25 messages from 2008-10-31 to 2008-11-05. Participants: Jeff King, Sam Vilain, Pierre Habouzit, Johannes Schindelin, Theodore Tso, Junio C Hamano, Jakub Narebski, Sverre Rabbelier, Dmitry Potapov.
Thread: https://gitlist.dev/t/16104

## Jeff King, 2008-10-31 00:31

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081031003154.GA5745@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20081031003154.GA5745%40sigill.intra.peff.net
In-Reply-To: <20081030002239.D453B21D14E@mail.utsl.gen.nz>

```
On Wed, Oct 29, 2008 at 05:22:00PM -0700, Sam Vilain wrote:

>  Some suggestions, which have been briefly scanned over by some of the
>  (remaining) GitTogether attendees.  Please keep it constructive!  :)

Thanks for putting this together.

> +  * 'git stage' would do what 'git add' does now.
> +
> +  * 'git unstage' would do what 'git reset --' does now

These seem reasonable.

> +  * 'git status' would encourage the user to use
> +    'git diff --staged' to see staged changes as a patch

I notice the commit template message getting longer and longer. Maybe it
is time for status.verbosetemplate (which could default to true, I just
want to be able to turn it off).

> +  * 'git commit' with no changes should give useful information about
> +    using 'git stage', 'git commit -a' or 'git commit filename ...'

There is already infrastructure that figures out exactly what the
situation is (no changes versus changes in untracked files versus
changes in unstaged files), so it should just be a matter of tweaking
the messages.

> +  * 'git add' and 'git rm': no change
> +
> +  * 'git update-index' considered plumbing, not changed

Definitely.

> +  * 'git revert' deprecated in favour of 'git cherry-pick --revert'

I think I would make it "-R, --reverse", since it really is analagous to
"git diff -R".

> +  * 'git undo' would do what 'git checkout HEAD --' does now

This is an awful name, IMHO. It doesn't point out _what_ you're undoing,
so it leaves me with the feeling that you can undo arbitrary things.
I think the name needs to be considered along with related operations.

So think of us as having three "spots": the HEAD (H), the "stage"[1] (S),
and the working tree (W). And we want commands for moving content
between them. Now we have:

  W->S: add
  H->S: reset --
  S->W: checkout --
  S->H: commit (no paths)

And if you want to include things that jump the staging area:

  W->H: commit (paths or -a)
  H->W: checkout HEAD --

So I think with your stage/unstage, we have:

  W->S: stage
  H->S: unstage
  S->W: ?
  S->H: commit (no paths)
  W->H: commit (paths or -a)
  H->W: ?

So I think we can note something: movement commands are related based on
their _destination_. So since both of the missing ones impact the
working tree, they should have a related name.

But do note the difference between "stage vs unstage" as opposed to
"commit versus commit -a". I think this is because the stage sits in the
middle. So it is mentally "which direction are changes coming from" and
not "how _far_ are changes coming from".

So by that rationale, we should have a single command which says "put
stuff in the working tree", with a flag for "from HEAD" versus "from the
staging area." And that's what we have right now with "git checkout".
The real problem with it is that it is an overload of checkout's other
behavior of switching branches.

So what I am saying is "git undo" _must_ support both "put index content
into working tree" as well as "put HEAD content into working tree", or
it will be a step backwards in consistency.

So I guess that doesn't really suggest a name. But "undo" is awful. ;P

Side note: there are actually _other_ places you might want to move
content. Like a stash. So now you can think of it as:

                 stash
                  ^  ^
                 /    \
                /      \
               v        v
  HEAD <--> stage <--> working tree

So maybe we just need a "git content" command. And then you can "git
content --from=HEAD --to=tree <paths>" or "git content --from=tree
--to=stash", with all equally supporting "--interactive".  And of course
I am kidding, because typing that would be awful. But I think
conceptually, it makes sense. To me, anyway.

> +  * 'git branch --switch' : alternative to checkout

Blech. I think switching branches is the one thing that checkout does
unconfusedly. And this is much more typing. Not to mention that So I
would rather see "git switch" if checkout is somehow unpalatable.

But I don't know that it is. This seems like an attempt to say "branch
operations should all be part of 'git branch'". But checkout isn't
necessarily a branch operation. Consider detaching HEAD to a tag. Should
it be "git tag --switch"?

> +  * 'git push --matching' does what 'git push' does today (without
> +    explicit configuration)

I think this is reasonable even without other changes, just to override
any configuration.

> +  * 'git push' with no ref args and no 'push =' configuration does
> +    what:
> +    'git push origin $(git symbolic-ref HEAD | sed "s!refs/heads/!!")'
> +    does today.  ie, it only pushes the current branch.
> +    If a branch was defined in branch.<name>.push, push to that ref
> +    instead of the matching one.  If there is no matching ref, and
> +    there is a branch.<name>.merge, push back there.

There was a thread between me and Junio some months ago that touched on
this. I don't remember all of the arguments, but it was resolved to keep
the current behavior. Any proposal along these lines should at least
revisit and respond to those arguments.

> +  * 'git push' to checked out branch of non-bare repository not
> +    allowed without special configuration.  Configuration available

I have this patch done and sitting in my repo, but I need to add the
"without special configuration" bit and add tests and docs.

> +Informational
> +-------------
> +
> +  * 'git branch' should default to '--color=auto -v'

This should at least be configurable (even if it defaults to "on"). "-v"
is more expensive, and not always wanted.

I, for one, just use "git branch" to get the current branch. I don't
know of a more obvious way to ask for it (and please don't mention an
ever-changing bash prompt).

> +  * 'git tag -l' should show more information

I remember somebody talking about this, but not the details. Which
information?

> +  * 'git am -3' the default; with global option to make it not the
> +    default for those that prefer the speed of -2

I would prefer that personally. I think Linus has been very reasonable
in the past about recognizing that his workflow and speed requirements
aren't always typical, and being willing to accept setting a
configuration flag in those cases. So I think if he ack'd such a patch,
nobody else would complain.

> +  * 'git export' command that does what
> +    'git archive --format=tar --prefix=dir | tar x' does now

I agree, if you mean "does what ... does now" means "looks to the user
like ... is happening". This is much more sanely done using
git-checkout-index (though somebody suggested "remote export", which
would need to use tar itself).

> +  * 'git init --server' (or similar) should do everything required for
> +    exporting::
> +----
> +chmod -R a+rX
> +touch git-daemon-export-ok
> +git gc
> +git update-server-info
> +chmod u+x .git/hooks/post-update
> +git config core.sharedrepository=1
> +----

But not all of those things are necessarily related, and some of them
have security implications. I would hate to get a bug report like "I
used --server because I wanted to share my content via dumb http, but my
repo was p0wned because of too-loose group permissions."

-Peff

```

## Sam Vilain, 2008-10-31 06:40

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <1225435238.20883.18.camel@maia.lan>
URL: https://gitlist.dev/e/1225435238.20883.18.camel%40maia.lan
In-Reply-To: <20081031003154.GA5745@sigill.intra.peff.net>

```
On Thu, 2008-10-30 at 20:31 -0400, Jeff King wrote:
> >  Some suggestions, which have been briefly scanned over by some of the
> >  (remaining) GitTogether attendees.  Please keep it constructive!  :)
> Thanks for putting this together.

No problem!  Thanks for responding.  I've been amazed that it seems to
have been largely taken well :)  But there are still very important
changes required.

> > +  * 'git status' would encourage the user to use
> > +    'git diff --staged' to see staged changes as a patch
> 
> I notice the commit template message getting longer and longer. Maybe it
> is time for status.verbosetemplate (which could default to true, I just
> want to be able to turn it off).

Right.  We'll have to work through that when we look at how 'git status'
output is displayed.  There may be some people who parse the existing
output, but they should get to read the release notes about the proper
ways to do that.  I think the whole output could do with a shake-up.

> > +  * 'git undo' would do what 'git checkout HEAD --' does now
> This is an awful name, IMHO. It doesn't point out _what_ you're undoing,

As others have said, yes.

> So I think with your stage/unstage, we have:
> 
>   W->S: stage
>   H->S: unstage
>   S->W: ?
>   S->H: commit (no paths)
>   W->H: commit (paths or -a)
>   H->W: ?
> 
> So I think we can note something: movement commands are related based on
> their _destination_. So since both of the missing ones impact the
> working tree, they should have a related name.

An interesting observation.

I still think it's OK to use 'git revert-files' for this; it just seems
so long.  Switches could specify where to and from.

> Side note: there are actually _other_ places you might want to move
> content. Like a stash. So now you can think of it as:
> 
>                  stash
>                   ^  ^
>                  /    \
>                 /      \
>                v        v
>   HEAD <--> stage <--> working tree
> 
> So maybe we just need a "git content" command. And then you can "git
> content --from=HEAD --to=tree <paths>" or "git content --from=tree
> --to=stash", with all equally supporting "--interactive".  And of course
> I am kidding, because typing that would be awful. But I think
> conceptually, it makes sense. To me, anyway.

Again interesting, you could look at the stash as a whole bunch of
staged commits yet to happen.  Of course, adding a file when the version
in HEAD doesn't match the version in the base of the stash is a bit
insane, so should probably be an error.

I'll have a ponder over this and whether there is a simple word for this
all.

> > +  * 'git branch --switch' : alternative to checkout
> 
> Blech. I think switching branches is the one thing that checkout does
> unconfusedly. And this is much more typing. Not to mention that So I
> would rather see "git switch" if checkout is somehow unpalatable.
>
> But I don't know that it is. This seems like an attempt to say "branch
> operations should all be part of 'git branch'". But checkout isn't
> necessarily a branch operation. Consider detaching HEAD to a tag. Should
> it be "git tag --switch"?

You're right with all that.  I don't think that it is necessarily wrong
to have two ways to get at functionality, depending on whether you start
with the noun or the verb first; so long as it doesn't introduce
confusion.  And if anything, I think --switch is wrong; --checkout is
probably more consistent.

I think I might have to mark this one as [maybe], and make it --checkout
- as you say, it would need to go on all the other commands that are
nouns and able to be checked out to be consistent.  Let's see how that
looks in round 2.

> > +  * 'git push --matching' does what 'git push' does today (without
> > +    explicit configuration)
> 
> I think this is reasonable even without other changes, just to override
> any configuration.

Excellent, I have another vote towards this push sanity!  :)

> > +  * 'git push' with no ref args and no 'push =' configuration does
> > +    what:
> > +    'git push origin $(git symbolic-ref HEAD | sed "s!refs/heads/!!")'
> > +    does today.  ie, it only pushes the current branch.
> > +    If a branch was defined in branch.<name>.push, push to that ref
> > +    instead of the matching one.  If there is no matching ref, and
> > +    there is a branch.<name>.merge, push back there.
> 
> There was a thread between me and Junio some months ago that touched on
> this. I don't remember all of the arguments, but it was resolved to keep
> the current behavior. Any proposal along these lines should at least
> revisit and respond to those arguments.

Right.  So, before round 2, I'll read and attempt to summarise that
thread - assuming I can find it!  :)

> > +  * 'git push' to checked out branch of non-bare repository not
> > +    allowed without special configuration.  Configuration available
> I have this patch done and sitting in my repo, but I need to add the
> "without special configuration" bit and add tests and docs.

Looking forward to that!  Thanks.

> > +  * 'git branch' should default to '--color=auto -v'
> This should at least be configurable (even if it defaults to "on"). "-v"
> is more expensive, and not always wanted.
> 
> I, for one, just use "git branch" to get the current branch. I don't
> know of a more obvious way to ask for it (and please don't mention an
> ever-changing bash prompt).

What's wrong with 'git symbolic-ref HEAD' ?  *ducks*

Of course 'git branch -q' would then be the quick version, or 'git
br' (after git config --global alias.br 'branch -q')

Another command people often want is 'git info' to tell them stuff like
they might get from 'git status' or 'git remote' but without all the
file details...

> > +  * 'git tag -l' should show more information
> 
> I remember somebody talking about this, but not the details. Which
> information?

Oh, good point.  Basically the same stuff that 'git branch -v' shows; in
any case, its behaviour should be relatively consistent compared to 'git
branch'.

> > +  * 'git init --server' (or similar) should do everything required for
> > +    exporting::
> > +----
> > +chmod -R a+rX
> > +touch git-daemon-export-ok
> > +git gc
> > +git update-server-info
> > +chmod u+x .git/hooks/post-update
> > +git config core.sharedrepository=1
> > +----
> 
> But not all of those things are necessarily related, and some of them
> have security implications. I would hate to get a bug report like "I
> used --server because I wanted to share my content via dumb http, but my
> repo was p0wned because of too-loose group permissions."

ok.  That should come down to the detail of how '--server' is specified,
I think.  I'll expand on that during round 2.

Sam.

```

## Pierre Habouzit, 2008-10-31 08:20

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081031082015.GA21015@artemis.corp>
URL: https://gitlist.dev/e/20081031082015.GA21015%40artemis.corp
In-Reply-To: <1225435238.20883.18.camel@maia.lan>

```
On Fri, Oct 31, 2008 at 06:40:38AM +0000, Sam Vilain wrote:
> On Thu, 2008-10-30 at 20:31 -0400, Jeff King wrote:
> > >  Some suggestions, which have been briefly scanned over by some of the
> > >  (remaining) GitTogether attendees.  Please keep it constructive!  :)
> > Thanks for putting this together.
> 
> No problem!  Thanks for responding.  I've been amazed that it seems to
> have been largely taken well :)  But there are still very important
> changes required.

Well, most of it we discussed IRL, that helps tremendously ;)

> I still think it's OK to use 'git revert-files' for this; it just seems
> so long.  Switches could specify where to and from.

Well the point is we will probably just deprecate git-revert and remove
it alltogether in git 2.6. At that time you will be able to define
git-revert as an alias to git cherry-pick -R if you're an old fart, or
git revert-files if you're an svn user ;)

But I see no convincing name that hasn't "revert" in them, hence will be
long :/

> Of course 'git branch -q' would then be the quick version, or 'git
> br' (after git config --global alias.br 'branch -q')

oh no, not -q please, -q is quiet, -h is help, -v is verbose. I mean
POSIX should define these. Do not give those switch any other kind of
sementics anymore, we've done that, and it hurts. -Q is fine with me
though.

> Another command people often want is 'git info' to tell them stuff like
> they might get from 'git status' or 'git remote' but without all the
> file details...

And to say to them if they're in the midle of a merge, of a rebase, an
am, on a detached, head, .... what is in the __git_ps1 of bash actually.

> > > +  * 'git init --server' (or similar) should do everything required for
> > > +    exporting::
> > > +----
> > > +chmod -R a+rX
> > > +touch git-daemon-export-ok
> > > +git gc
> > > +git update-server-info
> > > +chmod u+x .git/hooks/post-update
> > > +git config core.sharedrepository=1
> > > +----
> > 
> > But not all of those things are necessarily related, and some of them
> > have security implications. I would hate to get a bug report like "I
> > used --server because I wanted to share my content via dumb http, but my
> > repo was p0wned because of too-loose group permissions."
> 
> ok.  That should come down to the detail of how '--server' is specified,
> I think.  I'll expand on that during round 2.

What about git init --svn-like ? /me *ducks*

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

```

## Johannes Schindelin, 2008-10-31 16:46

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <alpine.DEB.1.00.0810311745030.22125@pacific.mpi-cbg.de.mpi-cbg.de>
URL: https://gitlist.dev/e/alpine.DEB.1.00.0810311745030.22125%40pacific.mpi-cbg.de.mpi-cbg.de
In-Reply-To: <20081031003154.GA5745@sigill.intra.peff.net>

```
Hi,

On Thu, 30 Oct 2008, Jeff King wrote:

> On Wed, Oct 29, 2008 at 05:22:00PM -0700, Sam Vilain wrote:
> 
> > +  * 'git branch --switch' : alternative to checkout
> 
> Blech. I think switching branches is the one thing that checkout does 
> unconfusedly. And this is much more typing. Not to mention that So I 
> would rather see "git switch" if checkout is somehow unpalatable.

You know, I asked for this because a _user_ told me "Guess how long it 
took me to find out how to check out a branch!".

I think if you are not confused by CVS/SVN, the name "checkout" is utterly 
unintuitive.

Ciao,
Dscho

```

## Jeff King, 2008-11-02 03:42

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081102034224.GA5261@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081102034224.GA5261%40coredump.intra.peff.net
In-Reply-To: <alpine.DEB.1.00.0810311745030.22125@pacific.mpi-cbg.de.mpi-cbg.de>

```
On Fri, Oct 31, 2008 at 05:46:35PM +0100, Johannes Schindelin wrote:

> > > +  * 'git branch --switch' : alternative to checkout
> > 
> > Blech. I think switching branches is the one thing that checkout does 
> > unconfusedly. And this is much more typing. Not to mention that So I 
> > would rather see "git switch" if checkout is somehow unpalatable.
> 
> You know, I asked for this because a _user_ told me "Guess how long it 
> took me to find out how to check out a branch!".
> 
> I think if you are not confused by CVS/SVN, the name "checkout" is utterly 
> unintuitive.

OK. I am not opposed to such a change as long as:

 - this is not just _a_ user, but a _common_ user confusion. IOW, I
   don't recall this complaint coming up a lot (or at least not nearly
   as often as other ones do). But maybe you have more data.

 - it is done consistently.

   My initial "blech" was a little premature, as I was thinking "instead
   of checkout", though it does clearly say "alternative" there.

   However, (and somebody else in the thread very cleverly came up with
   this analysis, not me), this is basically going from "verb the noun"
   to "noun --verb". And that's reasonable, if users think in terms of
   nouns. But we should be consistent in applying that transformation,
   and make it available for other nouns that match that verb. In other
   words, "git tag --switch". And however one might manipulate remote
   tracking branches ("git branch -r --switch", I guess).

   Personally I find it somewhat backwards, but I think CVS rotted my
   brain long ago.

-Peff

```

## Jeff King, 2008-11-02 03:53

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081102035310.GA5357@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081102035310.GA5357%40coredump.intra.peff.net
In-Reply-To: <20081031003154.GA5745@sigill.intra.peff.net>

```
On Thu, Oct 30, 2008 at 08:31:54PM -0400, Jeff King wrote:

> So think of us as having three "spots": the HEAD (H), the "stage"[1] (S),
> and the working tree (W). And we want commands for moving content

Re-reading this, I realized I forgot to fill in my footnote. But it was
going to be:

 [1] Actually, the term "the stage" is growing on me.

-Peff

```

## Jeff King, 2008-11-02 04:18

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081102041832.GB5261@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081102041832.GB5261%40coredump.intra.peff.net
In-Reply-To: <1225435238.20883.18.camel@maia.lan>

```
On Thu, Oct 30, 2008 at 11:40:38PM -0700, Sam Vilain wrote:

> > I notice the commit template message getting longer and longer. Maybe it
> > is time for status.verbosetemplate (which could default to true, I just
> > want to be able to turn it off).
> Right.  We'll have to work through that when we look at how 'git status'
> output is displayed.  There may be some people who parse the existing
> output, but they should get to read the release notes about the proper
> ways to do that.  I think the whole output could do with a shake-up.

Maybe I am wrong, but I thought at some point we decided that parsing
the output of "git status" was insane and wrong, since it's porcelain.
OTOH, it is also an easy way for editors to see what is happening in a
commit whose message you are editing (and to do, for example, syntax
highlighting on it). So it may be that it is getting parsed anyway.

> [moving content from HEAD or index to working tree]
> I still think it's OK to use 'git revert-files' for this; it just seems
> so long.  Switches could specify where to and from.

Yeah, revert-files is pretty painful to type. And I'm not looking
forward to fielding UI questions about "why isn't it just revert?" :)

Somebody suggested "clobber", which I think is a bit _too_ intense.

I guess something like "retrieve" is too ambiguous. You really need
something that implies movement of content, and something that implies
the working directory. "Checkout" is actually not a bad name; if only we
had "git switch" instead of "git checkout" for switching branches, it
would be perfect.

So I am a bit stumped. Maybe "clobber" is not so bad. ;)

> Again interesting, you could look at the stash as a whole bunch of
> staged commits yet to happen.  Of course, adding a file when the version
> in HEAD doesn't match the version in the base of the stash is a bit
> insane, so should probably be an error.
> 
> I'll have a ponder over this and whether there is a simple word for this
> all.

Whether or not we come up with a simple word, I think it makes sense to
expose this through "git stash -i" (since, after all, we are just
putting stuff into an index there).

> You're right with all that.  I don't think that it is necessarily wrong
> to have two ways to get at functionality, depending on whether you start
> with the noun or the verb first; so long as it doesn't introduce
> confusion.  And if anything, I think --switch is wrong; --checkout is
> probably more consistent.

Agreed on --checkout. I think your "noun or verb" comment hits the nail
right on the head. I wonder if there are other places where
functionality can be exposed in either direction (I think we already
have some in "git fetch <remote>" versus "git remote update").

> > There was a thread between me and Junio some months ago that touched on
> > this. I don't remember all of the arguments, but it was resolved to keep
> > the current behavior. Any proposal along these lines should at least
> > revisit and respond to those arguments.
> 
> Right.  So, before round 2, I'll read and attempt to summarise that
> thread - assuming I can find it!  :)

I think it was "Minor annoyance with git push" from this past February.
Quite a long thread, but there is some in this subthread:

http://thread.gmane.org/gmane.comp.version-control.git/73038/focus=73208

> Another command people often want is 'git info' to tell them stuff like
> they might get from 'git status' or 'git remote' but without all the
> file details...

Yeah, I don't know if you have followed the other threads in the past
month or so, but I think there is some desire for a "new" status with
a nicer format.

And I think it might be nice to structure it as a long list of things it
_can_ report on, and then let you tweak those with command-line options
and config settings. E.g., I might set info.currentbranch, info.staged,
and info.untracked because that is what _I_ like to see to get a sense
of what is happening in the repo.

And I will get around to designing that after I clear the other 100
things off my todo list. ;)

> > > +  * 'git tag -l' should show more information
> > I remember somebody talking about this, but not the details. Which
> > information?
> Oh, good point.  Basically the same stuff that 'git branch -v' shows; in
> any case, its behaviour should be relatively consistent compared to 'git
> branch'.

OK, that makes sense to me. I think of "git tag -l" as plumbing-ish,
though, so we might be breaking people's scripts (yes, I know the "real"
plumbing for this is for-each-ref, but it really is a pain to parse the
tags out of that versus "for i in `git tag -l`").

-Peff

```

## Theodore Tso, 2008-11-02 09:56

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081102095658.GH8134@mit.edu>
URL: https://gitlist.dev/e/20081102095658.GH8134%40mit.edu
In-Reply-To: <20081102041832.GB5261@coredump.intra.peff.net>

```
On Sun, Nov 02, 2008 at 12:18:33AM -0400, Jeff King wrote:
> 
> Yeah, revert-files is pretty painful to type. And I'm not looking
> forward to fielding UI questions about "why isn't it just revert?" :)
> 

At least for me, I don't use it *that* often, so it's not that painful
for me (I have it as an "git revert-file" as an alias already).   

And the answer, "because 'git revert' used to do something else" is I
think a perfectly reasonable answer.  I probably do "git revert-files"
about 3-5 times more often than I do "git revert", so it's a bit
strange from a character count perspective, but history is history.

> Somebody suggested "clobber", which I think is a bit _too_ intense.
> 
> I guess something like "retrieve" is too ambiguous. You really need
> something that implies movement of content, and something that implies
> the working directory. "Checkout" is actually not a bad name; if only we
> had "git switch" instead of "git checkout" for switching branches, it
> would be perfect.

If people really want a shorter name, how about bk's "unedit"?  I'd
still worry about people being able to find it, since the reality is
that most of the world knows this command as revert, though.

     	     	       	     	  	     	     - Ted

```

## Junio C Hamano, 2008-11-02 22:27

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <7v3ai9226q.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7v3ai9226q.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20081031003154.GA5745@sigill.intra.peff.net>

```
Jeff King <peff@peff.net> writes:

>> +  * 'git push --matching' does what 'git push' does today (without
>> +    explicit configuration)
>
> I think this is reasonable even without other changes, just to override
> any configuration.

I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
recall that there is a way to configure push that way for people too lazy
to type "origin HEAD" after "git push".

>> +  * 'git export' command that does what
>> +    'git archive --format=tar --prefix=dir | tar x' does now
>
> I agree, if you mean "does what ... does now" means "looks to the user
> like ... is happening". This is much more sanely done using
> git-checkout-index (though somebody suggested "remote export", which
> would need to use tar itself).

I think I was neutral in the discussion that led to the removal of
"git-export", but the rationale IIRC was exactly because "git-export" can
be done by simply piping "git-tar" to tar.  On the other hand, if all you
had was "export" and you wanted to create a release tar/zip ball, you have
to first create a (potentially huge) hierarchy in the filesystem only to
archive it.  This change needs to defend that the benefit of being able to
create a new non-git checkout elsewhere on the filesystem far outweighs
the downside of addition of another command (i.e. "eek, why does git have
that many commands" from new people).

```

## Sam Vilain, 2008-11-03 05:59

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <1225691960.20883.41.camel@maia.lan>
URL: https://gitlist.dev/e/1225691960.20883.41.camel%40maia.lan
In-Reply-To: <7v3ai9226q.fsf@gitster.siamese.dyndns.org>

```
On Sun, 2008-11-02 at 14:27 -0800, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
> 
> >> +  * 'git push --matching' does what 'git push' does today (without
> >> +    explicit configuration)
> >
> > I think this is reasonable even without other changes, just to override
> > any configuration.
> 
> I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
> recall that there is a way to configure push that way for people too lazy
> to type "origin HEAD" after "git push".

I don't think it's about laziness, it's more about making sure that
without specifying behaviour, the action of the command is conservative.
Pushing all matching refs is not conservative; it's "magic".  And in my
experience, people get bitten by it, because they think, "ok, time to
push this branch", type "git push" and then a lot more than they
expected gets pushed.

I can see that some people want this behaviour by default; but to me
"push the current branch back to where it came from" seems like far more
a rational default for at least 90% of users.

Sam.

```

## Jeff King, 2008-11-03 06:56

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081103065636.GB10772@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081103065636.GB10772%40coredump.intra.peff.net
In-Reply-To: <7v3ai9226q.fsf@gitster.siamese.dyndns.org>

```
On Sun, Nov 02, 2008 at 02:27:57PM -0800, Junio C Hamano wrote:

> >> +  * 'git push --matching' does what 'git push' does today (without
> >> +    explicit configuration)
> >
> > I think this is reasonable even without other changes, just to override
> > any configuration.
> 
> I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
> recall that there is a way to configure push that way for people too lazy
> to type "origin HEAD" after "git push".

I think you are reading more into my statement than I intended. I meant
that adding an explicit --matching was reasonable, _even if it matches
the default_. I can think of two reasons:

 1. Even if it is a no-op, it is more explicit for showing newbies what
    is going on. And it also means that _if_ we wanted to introduce
    new behavior or configurability, we will have already had
    "--matching" for some time. So it will be safe(r) at that point to
    immediately start saying "--matching" in your scripts to specify the
    behavior you want, without as much worry about confusing an older
    version.

 2. Even today, the behavior of push can be modified with configuration
    in remote.*.mirror. I would expect "git push --matching" to override
    this. Though perhaps that is too confusing a behavior, as mirroring
    does more than just ref selection, including force-updating.

So my statement was not anything about "git push $there HEAD", but just
that adding "--matching" was reasonable.

> I think I was neutral in the discussion that led to the removal of
> "git-export", but the rationale IIRC was exactly because "git-export" can
> be done by simply piping "git-tar" to tar.  On the other hand, if all you
> had was "export" and you wanted to create a release tar/zip ball, you have
> to first create a (potentially huge) hierarchy in the filesystem only to
> archive it.  This change needs to defend that the benefit of being able to
> create a new non-git checkout elsewhere on the filesystem far outweighs
> the downside of addition of another command (i.e. "eek, why does git have
> that many commands" from new people).

I think the complaint is just that it is awkward to have to pipe to tar
(and harder to check error status), when "export to directory" is a
reasonably common request.

If the concern is about another command, then perhaps rather than "git
export" it would be simpler to have "git archive --format=dir" as a
convenience (and it could even use the checkout-index optimization in
the local case, rather than generating a tar).

-Peff

```

## Jeff King, 2008-11-03 06:59

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081103065941.GA10961@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081103065941.GA10961%40coredump.intra.peff.net
In-Reply-To: <20081103065636.GB10772@coredump.intra.peff.net>

```
On Mon, Nov 03, 2008 at 01:56:36AM -0500, Jeff King wrote:

> So my statement was not anything about "git push $there HEAD", but just
> that adding "--matching" was reasonable.

And btw, I am not saying I necessarily disagree with Sam's proposal
about bare "git push". I am undecided about the best course of action
there.

I just wanted to make clear that it was not what I was talking about in
the original mail.

-Peff

```

## Pierre Habouzit, 2008-11-03 09:25

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081103092507.GD13930@artemis.corp>
URL: https://gitlist.dev/e/20081103092507.GD13930%40artemis.corp
In-Reply-To: <7v3ai9226q.fsf@gitster.siamese.dyndns.org>

```
On Sun, Nov 02, 2008 at 10:27:57PM +0000, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
> 
> >> +  * 'git push --matching' does what 'git push' does today (without
> >> +    explicit configuration)
> >
> > I think this is reasonable even without other changes, just to override
> > any configuration.
> 
> I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
> recall that there is a way to configure push that way for people too lazy
> to type "origin HEAD" after "git push".

Yes, but it's broken in the sense that if you're in a non matching
branch it creates it remotely. The way to configure it is to say
remote.push = HEAD in your .gitconfig or sth similar. I removed it
because I've created 2 times a new branch remotely that I didn't want to
because I was tired and forgot to checkout and merge into the proper
one.

I rarely do mistakes with git, but something like more than half of my
mistakes are with push. I've argued that in the past, I know most of the
other core git developers disagree with the fact that git-push UI is not
helping users to not shoot themselves in the foot, I disagree, but there
is not much I can do if I'm 1:10 to think that ;)
-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

```

## Jakub Narebski, 2008-11-03 09:48

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <gemhdp$lev$1@ger.gmane.org>
URL: https://gitlist.dev/e/gemhdp%24lev%241%40ger.gmane.org
In-Reply-To: <1225691960.20883.41.camel@maia.lan>

```
Sam Vilain wrote:
> On Sun, 2008-11-02 at 14:27 -0800, Junio C Hamano wrote:
>> Jeff King <peff@peff.net> writes:
>> 
>>>> +  * 'git push --matching' does what 'git push' does today (without
>>>> +    explicit configuration)
>>>
>>> I think this is reasonable even without other changes, just to override
>>> any configuration.
>> 
>> I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
>> recall that there is a way to configure push that way for people too lazy
>> to type "origin HEAD" after "git push".
> 
> I don't think it's about laziness, it's more about making sure that
> without specifying behaviour, the action of the command is conservative.
> Pushing all matching refs is not conservative; it's "magic".  And in my
> experience, people get bitten by it, because they think, "ok, time to
> push this branch", type "git push" and then a lot more than they
> expected gets pushed.
> 
> I can see that some people want this behaviour by default; but to me
> "push the current branch back to where it came from" seems like far more
> a rational default for at least 90% of users.

"git remote <remote> push" for push matching?

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

```

## Sverre Rabbelier, 2008-11-03 09:53

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <bd6139dc0811030153o669a2cfax6fb9ef5e6d3e294e@mail.gmail.com>
URL: https://gitlist.dev/e/bd6139dc0811030153o669a2cfax6fb9ef5e6d3e294e%40mail.gmail.com
In-Reply-To: <gemhdp$lev$1@ger.gmane.org>

```
On Mon, Nov 3, 2008 at 10:48, Jakub Narebski <jnareb@gmail.com> wrote:
> "git remote <remote> push" for push matching?

Not another command that is made to perform yet another piece of
funcionality. Let's let remote handle (configuring, and maintaining
of) remote related things, not also make it do push stuff.
Unless ofcourse, you mean that "git remote push <remote>" (certainly
not the other way around) is for configuration only.

-- 
Cheers,

Sverre Rabbelier

```

## Junio C Hamano, 2008-11-03 23:33

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <7v4p2ov0zt.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7v4p2ov0zt.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20081103092507.GD13930@artemis.corp>

```
Pierre Habouzit <madcoder@debian.org> writes:

> On Sun, Nov 02, 2008 at 10:27:57PM +0000, Junio C Hamano wrote:
>> Jeff King <peff@peff.net> writes:
>> 
>> >> +  * 'git push --matching' does what 'git push' does today (without
>> >> +    explicit configuration)
>> >
>> > I think this is reasonable even without other changes, just to override
>> > any configuration.
>> 
>> I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
>> recall that there is a way to configure push that way for people too lazy
>> to type "origin HEAD" after "git push".
>
> Yes, but it's broken in the sense that if you're in a non matching
> branch it creates it remotely.

Ok, I agree that may be a problem.

But that would not change if you only changed the default behaviour from
matching to _this branch_.  You need to also teach a new mode of operation
to send-pack/receive-pack pair, which is to "update the same branch as the
one I am on locally, but do not do anything if there is no such branch
over there".  I do not think we have such a mode of operation currently.

By the way, didn't we add a feature to let you say "git push $there :"
which is to do what "git push --matching $there" would do?

```

## Pierre Habouzit, 2008-11-04 00:02

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081104000207.GA29458@artemis.corp>
URL: https://gitlist.dev/e/20081104000207.GA29458%40artemis.corp
In-Reply-To: <7v4p2ov0zt.fsf@gitster.siamese.dyndns.org>

```
On Mon, Nov 03, 2008 at 11:33:10PM +0000, Junio C Hamano wrote:
> Pierre Habouzit <madcoder@debian.org> writes:
> 
> > On Sun, Nov 02, 2008 at 10:27:57PM +0000, Junio C Hamano wrote:
> >> Jeff King <peff@peff.net> writes:
> >> 
> >> >> +  * 'git push --matching' does what 'git push' does today (without
> >> >> +    explicit configuration)
> >> >
> >> > I think this is reasonable even without other changes, just to override
> >> > any configuration.
> >> 
> >> I don't.  Can't you say "git push $there HEAD" these days?  I vaguely
> >> recall that there is a way to configure push that way for people too lazy
> >> to type "origin HEAD" after "git push".
> >
> > Yes, but it's broken in the sense that if you're in a non matching
> > branch it creates it remotely.
> 
> Ok, I agree that may be a problem.
> 
> But that would not change if you only changed the default behaviour from
> matching to _this branch_.  You need to also teach a new mode of operation
> to send-pack/receive-pack pair, which is to "update the same branch as the
> one I am on locally, but do not do anything if there is no such branch
> over there".  I do not think we have such a mode of operation currently.

You're right.

> By the way, didn't we add a feature to let you say "git push $there :"
> which is to do what "git push --matching $there" would do?

I don't know, I thought git push --matching $remote would be the same as
git push $remote ?

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

```

## Junio C Hamano, 2008-11-04 00:44

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <7vljw0tj49.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vljw0tj49.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20081104000207.GA29458@artemis.corp>

```
Pierre Habouzit <madcoder@debian.org> writes:

>> Ok, I agree that may be a problem.
>> 
>> But that would not change if you only changed the default behaviour from
>> matching to _this branch_.  You need to also teach a new mode of operation
>> to send-pack/receive-pack pair, which is to "update the same branch as the
>> one I am on locally, but do not do anything if there is no such branch
>> over there".  I do not think we have such a mode of operation currently.
>
> You're right.

Perhaps "git push --no-create"?

In hindsight, _if_ we did not have to worry about backward compatibility
at all, I might agree that the way "git push" ought to work with least
surprise would be:

 * "git push" is the same as "git push origin" (override 'origin' with
   branch.$current_branch.remote);

 * "git push $remote" is the same as "git push --no-create $remote HEAD"
   (override 'HEAD' with remote.$remote.push);

 * "git push $remote $any_non_empty_refspec" does what it is told without
   configuration interfering.

Current behaviour satisfies the first one and the third one.  Instead of
the second, the current behaviour is:

 * "git push $remote" is the same as "git push $remote :" (override ':'
   with remote.$remote.push).

>> By the way, didn't we add a feature to let you say "git push $there :"
>> which is to do what "git push --matching $there" would do?
>
> I don't know, I thought git push --matching $remote would be the same as
> git push $remote ?

I think the point of "push --matching" (or an explicit "push $there :") is
so that you can defeat what you configured.  For example, you could have:

	[branch "master"]
        	remote = gitster
	[remote "gitster"]
        	url = gitster:/pub/git/git.git/
                push = HEAD

And with such a configuration, "git push" or "git push gitster" would only
push to the current branch.

You can countermand with "push gitster master next", of course, but you
would need a way to ask for the matching from the command line without
listing all the names, hence you would say "push gitster :".

I think you meant to give the  --matching option the same efffect.  My
comment is that you do not need a new option, as we already have that
feature.

```

## Jeff King, 2008-11-04 05:20

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081104052024.GE31276@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081104052024.GE31276%40coredump.intra.peff.net
In-Reply-To: <7v4p2ov0zt.fsf@gitster.siamese.dyndns.org>

```
On Mon, Nov 03, 2008 at 03:33:10PM -0800, Junio C Hamano wrote:

> By the way, didn't we add a feature to let you say "git push $there :"
> which is to do what "git push --matching $there" would do?

Oh, indeed: a83619d (add special "matching refs" refspec) from April.
So given that, I think my arguments for "--matching" are pointless.

-Peff

```

## Dmitry Potapov, 2008-11-04 09:18

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081104091800.GB24100@dpotapov.dyndns.org>
URL: https://gitlist.dev/e/20081104091800.GB24100%40dpotapov.dyndns.org
In-Reply-To: <1225691960.20883.41.camel@maia.lan>

```
On Mon, Nov 03, 2008 at 06:59:20PM +1300, Sam Vilain wrote:
> 
> I can see that some people want this behaviour by default; but to me
> "push the current branch back to where it came from" seems like far more
> a rational default for at least 90% of users.

I think it depends on one's workflow. If you use a centralized workflow
as with CVS then yes, 90% cases you want to push the current branch. On
the other hand, if people push their changes to the server only for
review, it means that accidentally pushing more than one intended is not
a big deal. The only one who does publishing to the official repository
is the maintainer, and the maintainer is most likely to run some tests
after merging all changes, which takes some time. So, it is rarely push
the current branch, it is usually the branch that has been tested, so
the name of the branch should be specified explicitly anyway.

Dmitry

```

## Sam Vilain, 2008-11-04 18:10

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <1225822231.6722.3.camel@maia.lan>
URL: https://gitlist.dev/e/1225822231.6722.3.camel%40maia.lan
In-Reply-To: <20081104091800.GB24100@dpotapov.dyndns.org>

```
On Tue, 2008-11-04 at 12:18 +0300, Dmitry Potapov wrote:
> > I can see that some people want this behaviour by default; but to me
> > "push the current branch back to where it came from" seems like far more
> > a rational default for at least 90% of users.
> 
> I think it depends on one's workflow. If you use a centralized workflow
> as with CVS then yes, 90% cases you want to push the current branch. On
> the other hand, if people push their changes to the server only for
> review, it means that accidentally pushing more than one intended is not
> a big deal.

Perhaps not, but it was still unintended.  I really can't understand the
opposition to making this command make many people less angry at it.

>  The only one who does publishing to the official repository
> is the maintainer, and the maintainer is most likely to run some tests
> after merging all changes, which takes some time. So, it is rarely push
> the current branch, it is usually the branch that has been tested, so
> the name of the branch should be specified explicitly anyway.

Why is that relevant?  That person can still use the explicit version of
the command.

Sam.

```

## Junio C Hamano, 2008-11-04 19:46

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <7vr65rqnoj.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vr65rqnoj.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <1225822231.6722.3.camel@maia.lan>

```
Sam Vilain <sam@vilain.net> writes:

> On Tue, 2008-11-04 at 12:18 +0300, Dmitry Potapov wrote:
> ...
>>  The only one who does publishing to the official repository
>> is the maintainer, and the maintainer is most likely to run some tests
>> after merging all changes, which takes some time. So, it is rarely push
>> the current branch, it is usually the branch that has been tested, so
>> the name of the branch should be specified explicitly anyway.
>
> Why is that relevant?  That person can still use the explicit version of
> the command.

Back when "git push $there :" were not available, the default matching
behaviour was the _only_ way to say "I know the set of branches I want to
publish, and I have many more private branches in my primary work
repository.  I do not want to list the set of branches to publish every
time when I type 'git push', nor I want to configure it --- Heck, I
shouldn't have to list them, the public repository I am pushing to already
has that list, and it is the set of branches that exist there".

These days, people who would want the maching behaviour can explicitly ask
for it, so there is one less reason to resist changing the default
(i.e. earlier explicitly askinf for "matching" was impossible, but now we
can).  The remaining reason of resistance is pure inertia (i.e. not
changing the behaviour of the command only because you upgraded your git),
and the only way to address it is to start issuing the warning when "git
push" or "git push $there" is used and the matching behaviour was chosen
without configuration (i.e. no "remote.<there>.push = :"), and keep it
that way for two release cycles, and finally change the default.

```

## Jeff King, 2008-11-05 03:05

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081105030525.GC20907@coredump.intra.peff.net>
URL: https://gitlist.dev/e/20081105030525.GC20907%40coredump.intra.peff.net
In-Reply-To: <7vr65rqnoj.fsf@gitster.siamese.dyndns.org>

```
On Tue, Nov 04, 2008 at 11:46:36AM -0800, Junio C Hamano wrote:

> These days, people who would want the maching behaviour can explicitly ask
> for it, so there is one less reason to resist changing the default
> (i.e. earlier explicitly askinf for "matching" was impossible, but now we
> can).  The remaining reason of resistance is pure inertia (i.e. not
> changing the behaviour of the command only because you upgraded your git),
> and the only way to address it is to start issuing the warning when "git
> push" or "git push $there" is used and the matching behaviour was chosen
> without configuration (i.e. no "remote.<there>.push = :"), and keep it
> that way for two release cycles, and finally change the default.

Hmm. It really seems to me that there are two desires for push behavior,
based on particular workflows. I.e., some people seem to want the
matching behavior by default, and others want to push the current
branch.

And we already can control that via configuration of the refspec. So any
argument that "git push should do the same thing even on somebody else's
setup" is already wrong. But I do think Junio has a good point, which is
that there is going to be confusion if upgrading git suddenly causes
"git push" to do something else.

So why not take one step back in the behavior change? We can set up the
"push just this branch" refspec during clone, which will leave existing
repositories untouched. And to make things even gentler, we can start
with opt-in to the clone feature, notify users via the release notes
(which, as we have established, EVERYONE reads), and then decide if and
when to switch the option on by default.

So something like a "remote.push" config option, the value of which gets
added to newly created remotes (including those created on clone). It
would default to ":", but you could easily set "git config remote.push
HEAD" to get the other behavior.

No, this doesn't get rid of the eventual need to choose whether to
switch the default. But I think it eases us into it a little more. And I
think such an option is a lot more generally applicable than a "default
push to matching versus HEAD" option.

-Peff

```

## Junio C Hamano, 2008-11-05 06:40

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <7vprlan09a.fsf@gitster.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vprlan09a.fsf%40gitster.siamese.dyndns.org
In-Reply-To: <20081105030525.GC20907@coredump.intra.peff.net>

```
Jeff King <peff@peff.net> writes:

> So why not take one step back in the behavior change? We can set up the
> "push just this branch" refspec during clone, which will leave existing
> repositories untouched.

That is not good enough.

People who (think) know what an unconfigured "git push" would do would
suddenly see "git push" start misbehaving in their new repositories.

Here is a patch to do what I suggested earlier.  It

 * Adds "--matching" option; if we ever change the default to "current
   branch only", then "git push $there :" forces people to type $there.
   "git push --matching" allows us to honor "branch.<name>.remote".

 * Issues a deprecation warning when "git push" and "git push $there" is
   used to trigger the "matching" behaviour, without configuration or
   explicit command line refspec ":".

Whoever wants to change the default to "current branch only" can change
the part that calls push_deprecation_warning().

I'll leave it up to people who want to change the default to implement the
same for non native transports and document the transition plan, as I am
not very keen on changing the default myself.

---

 builtin-push.c      |   11 +++++++----
 builtin-send-pack.c |    2 ++
 remote.c            |    8 ++++++++
 remote.h            |    1 +
 send-pack.h         |    1 +
 transport.c         |    1 +
 transport.h         |    1 +
 7 files changed, 21 insertions(+), 4 deletions(-)

diff --git c/builtin-push.c w/builtin-push.c
index 122fdcf..21418ab 100644
--- c/builtin-push.c
+++ w/builtin-push.c
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-	"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
+	"git push [--all | --mirror] [--dry-run] [--matching] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
 	NULL,
 };
 
@@ -71,9 +71,11 @@ static int do_push(const char *repo, int flags)
 		return error("--mirror can't be combined with refspecs");
 	}
 
-	if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
-				(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
-		return error("--all and --mirror are incompatible");
+	if (HAS_MULTI_BITS(flags &
+			   (TRANSPORT_PUSH_ALL|
+			    TRANSPORT_PUSH_MIRROR|
+			    TRANSPORT_PUSH_MATCHING))) {
+		return error("--all, --mirror, --matching are incompatible");
 	}
 
 	if (!refspec
@@ -123,6 +125,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
 		OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
 		OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
+		OPT_BIT( 0 , "matching", &flags, "push matching", TRANSPORT_PUSH_MATCHING),
 		OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
diff --git c/builtin-send-pack.c w/builtin-send-pack.c
index d68ce2d..f5dda88 100644
--- c/builtin-send-pack.c
+++ w/builtin-send-pack.c
@@ -402,6 +402,8 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		flags |= MATCH_REFS_ALL;
 	if (args.send_mirror)
 		flags |= MATCH_REFS_MIRROR;
+	if (args.send_matching)
+		flags |= MATCH_REFS_MATCHING;
 
 	/* No funny business with the matcher */
 	remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
diff --git c/remote.c w/remote.c
index e530a21..ce4f54c 100644
--- c/remote.c
+++ w/remote.c
@@ -1017,6 +1017,12 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
 		return NULL;
 }
 
+static void push_deprecation_warning(void)
+{
+	warning("'git push [$remote]' will stop pushing 'matching refs' in a future release");
+	warning("please train your fingers to say 'git push --matching' instead.");
+}
+
 /*
  * Note. This is used only by "push"; refspec matching rules for
  * push and fetch are subtly different, so do not try to reuse it
@@ -1031,6 +1037,8 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 	static const char *default_refspec[] = { ":", 0 };
 
 	if (!nr_refspec) {
+		if (!(flags & MATCH_REFS_MATCHING))
+			push_deprecation_warning();
 		nr_refspec = 1;
 		refspec = default_refspec;
 	}
diff --git c/remote.h w/remote.h
index d2e170c..2a702cb 100644
--- c/remote.h
+++ w/remote.h
@@ -124,6 +124,7 @@ enum match_refs_flags {
 	MATCH_REFS_NONE		= 0,
 	MATCH_REFS_ALL 		= (1 << 0),
 	MATCH_REFS_MIRROR	= (1 << 1),
+	MATCH_REFS_MATCHING	= (1 << 2),
 };
 
 /* Reporting of tracking info */
diff --git c/send-pack.h w/send-pack.h
index 8ff1dc3..133cb67 100644
--- c/send-pack.h
+++ w/send-pack.h
@@ -6,6 +6,7 @@ struct send_pack_args {
 	unsigned verbose:1,
 		send_all:1,
 		send_mirror:1,
+		send_matching:1,
 		force_update:1,
 		use_thin_pack:1,
 		dry_run:1;
diff --git c/transport.c w/transport.c
index 56831c5..4057d27 100644
--- c/transport.c
+++ w/transport.c
@@ -680,6 +680,7 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const
 	args.receivepack = data->receivepack;
 	args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
 	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
+	args.send_matching = !!(flags & TRANSPORT_PUSH_MATCHING);
 	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
 	args.use_thin_pack = data->thin;
 	args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
diff --git c/transport.h w/transport.h
index 6bbc1a8..fb98128 100644
--- c/transport.h
+++ w/transport.h
@@ -34,6 +34,7 @@ struct transport {
 #define TRANSPORT_PUSH_DRY_RUN 4
 #define TRANSPORT_PUSH_MIRROR 8
 #define TRANSPORT_PUSH_VERBOSE 16
+#define TRANSPORT_PUSH_MATCHING 32
 
 /* Returns a transport suitable for the url */
 struct transport *transport_get(struct remote *, const char *);

```

## Dmitry Potapov, 2008-11-05 22:53

Subject: Re: [PATCH] Documentation: add a planning document for the next CLI revamp
Message-ID: <20081105225327.GD24100@dpotapov.dyndns.org>
URL: https://gitlist.dev/e/20081105225327.GD24100%40dpotapov.dyndns.org
In-Reply-To: <1225822231.6722.3.camel@maia.lan>

```
On Wed, Nov 05, 2008 at 07:10:31AM +1300, Sam Vilain wrote:
> On Tue, 2008-11-04 at 12:18 +0300, Dmitry Potapov wrote:
> > > I can see that some people want this behaviour by default; but to me
> > > "push the current branch back to where it came from" seems like far more
> > > a rational default for at least 90% of users.
> > 
> > I think it depends on one's workflow. If you use a centralized workflow
> > as with CVS then yes, 90% cases you want to push the current branch. On
> > the other hand, if people push their changes to the server only for
> > review, it means that accidentally pushing more than one intended is not
> > a big deal.
> 
> Perhaps not, but it was still unintended.

Even if it were unintended, it will be noticed and corrected immediately,
while forgetting to push some changes is not so obvious... Anyway, your
workflow assumes that one wants to push changes immediately before
switching to another branch, while there are many people who do that
later (after some additional testing or just at the end of their workday).

> I really can't understand the
> opposition to making this command make many people less angry at it.

Because it breaks how this command works now. So I don't think it is a
good idea to make some people less angry while enraging many others over
breaking their workflow. Compatibility should not be taken lightly.

Dmitry

```
