threads / discuss / 13037

git annoyances

Subject: git annoyances

## tl;dr

86 messages between Apr 9, 2008 and Apr 23, 2008.

replies: 85people: 24as markdown or json

Ingo Molnar· Apr 9, 2008, 10:14 UTC · lore

i just had a rather annoying session with git - here's the dump and commentary, in case anyone is interested in usability fineprint.

it was with git-core-1.5.4.3-2.fc8 - so if it's all fixed/improved in 1.5.5, or if this is blatant user error for which i deserve to be punished then my apologies!

usually i just have a single git repo that tracks everything interesting, but this time i did something i rarely do: i tried to merge one local tree of mine into another local tree of mine. So i had no commands (or even concepts) cached in my short-term memory that would achieve this goal, i just tried the commands that i thought to be 'obvious', without applying much (or any) IQ to those commands:

 $ cd linux-2.6-sched-devel.git
 $ git-remote add ~/linux-2.6-x86.git
 $ git-remote show x86
  * remote x86
    URL: /home/mingo/linux-2.6-x86.git
  New remote branches (next fetch will store in remotes/x86)
  base for-akpm for-linus latest master testing
 $ git-merge x86/latest
 x86/latest - not something we can merge
 #
 # ho hum. Not something 'we' can merge. Do i care? :-) There's no 
 # actionable reference given to the user about how to resolve this 
 # problem. So i kept on trying:
 #
 $ git-fetch x86/latest
 fatal: 'x86/latest': unable to chdir or not a git archive
 fatal: The remote end hung up unexpectedly
 $ git-pull x86/latest
 fatal: 'x86/latest': unable to chdir or not a git archive
 fatal: The remote end hung up unexpectedly
 #
 # hm. two fatal messages, suggesting that there's something really 
 # wrong while there's nothing wrong.
 #

what got me going after experimenting around some more was this exact command:

 $ git-pull x86 latest
(that fetch+merge went problem-free.)

but it was a PITA and all of git's messages about the problem were not only unhelpful, they confused me into looking for problems where there were none IMO. I was starting to wonder whether i have to have some git daemon running on that box for example. But in retrospect IMO it was rather clear from the outset what i wanted git to do (merge the tip of my other tree into the tip of this tree, on the local box, no frills), i just didnt figure out the exact command to do it.

another (minor) usability annoyance: one of the first things i tried was to verify the remote setup, via:

$ git-remote show
which gave me this answer:
 Usage: git remote show <remote>

then i tried git-remote show -a (to list all repositories, etc.) - what i didnt figure out was to show all repositories is to do a simple "git-remote". I think "git-remote show" should output all repositories, or at least indicate it in its help line what to do to get such a list. (for us poor sobs forgetting commandline details ;)

also, the first natural thing i did was to just type:
 $ git-merge ~/linux-2.6-x86.git/

which i naively assumed would sort things out for me and provide some reasonable default behavior - but instead it just gave an annoyingly unhelpful error message:

 /home/mingo/linux-2.6-x86.git/ - not something we can merge

there should really be a consciously established "route of failure resolution" - directing people towards relevant sources of information or commands when the git command-line utilities return some error due to user incompetence. Otherwise users just guess around and get frustrated.

also, i think this session also probably matches the newbie's experience about git, and making certain git operations so hard to achieve is certainly not a reassuring experience for them either. [ Or shall they all be filtered out as fundamentally incompetent people? ;-) ]

	Ingo
Björn Steinbrink· Apr 9, 2008, 10:41 UTC · re: Ingo Molnar · lore

Re: git annoyances

On 2008.04.09 12:14:28 +0200, Ingo Molnar wrote:
Show 23 quoted lines
> 
> i just had a rather annoying session with git - here's the dump and 
> commentary, in case anyone is interested in usability fineprint.
> 
> it was with git-core-1.5.4.3-2.fc8 - so if it's all fixed/improved in 
> 1.5.5, or if this is blatant user error for which i deserve to be 
> punished then my apologies!
> 
> usually i just have a single git repo that tracks everything 
> interesting, but this time i did something i rarely do: i tried to merge 
> one local tree of mine into another local tree of mine. So i had no 
> commands (or even concepts) cached in my short-term memory that would 
> achieve this goal, i just tried the commands that i thought to be 
> 'obvious', without applying much (or any) IQ to those commands:
> 
>  $ cd linux-2.6-sched-devel.git
> 
>  $ git-remote add ~/linux-2.6-x86.git
> 
>  $ git-remote show x86
>   * remote x86
>     URL: /home/mingo/linux-2.6-x86.git
>   New remote branches (next fetch will store in remotes/x86)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I gues that's key here. The remote was added, but you don't actually have fetched the branches yet. Thus the merge fails, but the pull with the correct syntax succeeded, because it does a fetch first.

Show 10 quoted lines
>   base for-akpm for-linus latest master testing
> 
>  $ git-merge x86/latest
>  x86/latest - not something we can merge
> 
>  #
>  # ho hum. Not something 'we' can merge. Do i care? :-) There's no 
>  # actionable reference given to the user about how to resolve this 
>  # problem. So i kept on trying:
>  #
No branch, no merge ;-)
Show 12 quoted lines
>  $ git-fetch x86/latest
>  fatal: 'x86/latest': unable to chdir or not a git archive
>  fatal: The remote end hung up unexpectedly
> 
>  $ git-pull x86/latest
>  fatal: 'x86/latest': unable to chdir or not a git archive
>  fatal: The remote end hung up unexpectedly
> 
>  #
>  # hm. two fatal messages, suggesting that there's something really 
>  # wrong while there's nothing wrong.
>  #
The syntax is "git pull <repository> <refspec>"

So you're trying to fetch/pull from a repository in "x86/latest", that path doesn't exist and that is pretty fatal as you cannot fetch/pull from a repository that doesn't exist.

Show 6 quoted lines
> what got me going after experimenting around some more was this exact 
> command:
> 
>  $ git-pull x86 latest
> 
> (that fetch+merge went problem-free.)
Yeah, correct syntax and pull does the fetch for you.
Show 9 quoted lines
> also, the first natural thing i did was to just type:
> 
>  $ git-merge ~/linux-2.6-x86.git/
> 
> which i naively assumed would sort things out for me and provide some 
> reasonable default behavior - but instead it just gave an annoyingly 
> unhelpful error message:
> 
>  /home/mingo/linux-2.6-x86.git/ - not something we can merge

AFAIK merge cannot handle stuff that's outside your repo. To merge stuff from another repo without adding a remote, you have to use pull (or manually do the fetch+merge dance), ie.:

git pull ~/linux-2.6-x86.git latest
should do.
Björn
Jeff King· Apr 9, 2008, 14:57 UTC · re: Ingo Molnar · lore

Re: git annoyances

On Wed, Apr 09, 2008 at 12:14:28PM +0200, Ingo Molnar wrote:
Show 12 quoted lines
>  $ cd linux-2.6-sched-devel.git
> 
>  $ git-remote add ~/linux-2.6-x86.git
> 
>  $ git-remote show x86
>   * remote x86
>     URL: /home/mingo/linux-2.6-x86.git
>   New remote branches (next fetch will store in remotes/x86)
>   base for-akpm for-linus latest master testing
> 
>  $ git-merge x86/latest
>  x86/latest - not something we can merge

As you figured out later, the problem was that "git remote add" doesn't actually fetch the remote's contents: it just sets up the remote. There is a "-f" option which does the fetch automagically after adding.

In this case, had "-f" been the default, it would have Just Worked for you. So that's something for us to consider, but I'm not sure if we would annoy more users who _didn't_ want the fetch.

>  $ git-fetch x86/latest
>  fatal: 'x86/latest': unable to chdir or not a git archive
>  fatal: The remote end hung up unexpectedly

This is another place where we might have DWYM, by seeing that your repository name started with "<name of a remote>/" and splitting it into "<remote> <branch>". This could affect current usage, but it seems unlikely that people have remote names which are exact prefixes (with trailing slash) of non-remote repositories they are trying to fetch.

Reading "git help fetch" should show you the synopsis:
  git-fetch <options> <repository> <refspec>

which maybe gives a clue about the syntax. But I think the problem here is that there are two different syntaxes for what is _almost_ the same thing. The ref refs/remotes/x86/latest, which you can call "x86/latest" as a shorthand, and the (remote, refspec) pair (x86, latest).

>  $ git-pull x86 latest
> 
> (that fetch+merge went problem-free.)

Unless you are planning on merging this remote a lot, the common usage is probably to just forget the remote stuff and do:

  git pull ~/linux-2.6-x86.git latest
Show 5 quoted lines
> then i tried git-remote show -a (to list all repositories, etc.) - what 
> i didnt figure out was to show all repositories is to do a simple 
> "git-remote". I think "git-remote show" should output all repositories, 
> or at least indicate it in its help line what to do to get such a list. 
> (for us poor sobs forgetting commandline details ;)

Yes, just showing the remotes would be consistent with what other commands do (e.g., git-branch, git-tag). I'll post a patch in a minute.

Show 9 quoted lines
> also, the first natural thing i did was to just type:
> 
>  $ git-merge ~/linux-2.6-x86.git/
> 
> which i naively assumed would sort things out for me and provide some 
> reasonable default behavior - but instead it just gave an annoyingly 
> unhelpful error message:
> 
>  /home/mingo/linux-2.6-x86.git/ - not something we can merge

That is an annoying message. Perhaps we could notice that it looks like a file path (because it begins with '.') and suggest "maybe you wanted to "git pull ..."?

-Peff
Jeff King· Apr 9, 2008, 15:15 UTC · re: Jeff King · lore

[PATCH] git-remote: show all remotes with "git remote show"

Many other commands use the "no arguments" form to show a list (e.g., git-branch, git-tag). While we did show all remotes for just "git remote", we displayed a usage error for "git remote show" with no arguments. This is counterintuitive, since by giving it _more_ information, we get _less_ result.

The usage model can now be thought of as:
  - "git remote show <remote>": show a remote
  - "git remote show": show all remotes
  - "git remote": assume "show"; i.e., shorthand for "git remote show"
Signed-off-by: Jeff King <peff@peff.net>
---
On Wed, Apr 09, 2008 at 10:57:58AM -0400, Jeff King wrote:
Show 8 quoted lines
> > then i tried git-remote show -a (to list all repositories, etc.) - what 
> > i didnt figure out was to show all repositories is to do a simple 
> > "git-remote". I think "git-remote show" should output all repositories, 
> > or at least indicate it in its help line what to do to get such a list. 
> > (for us poor sobs forgetting commandline details ;)
> 
> Yes, just showing the remotes would be consistent with what other
> commands do (e.g., git-branch, git-tag). I'll post a patch in a minute.
And here it is.
 builtin-remote.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index d77f10a..06d33e5 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -19,6 +19,8 @@ static const char * const builtin_remote_usage[] = {
 
 static int verbose;
 
+static int show_all(void);
+
 static inline int postfixcmp(const char *string, const char *postfix)
 {
 	int len1 = strlen(string), len2 = strlen(postfix);
@@ -380,8 +382,11 @@ static int show_or_prune(int argc, const char **argv, int prune)
 
 	argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
 
-	if (argc < 1)
+	if (argc < 1) {
+		if (!prune)
+			return show_all();
 		usage_with_options(builtin_remote_usage, options);
+	}
 
 	memset(&states, 0, sizeof(states));
 	for (; argc; argc--, argv++) {
-- 
1.5.5.1.g272c
Johannes Schindelin· Apr 9, 2008, 16:54 UTC · re: Jeff King · lore

Re: [PATCH] git-remote: show all remotes with "git remote show"

Hi,
On Wed, 9 Apr 2008, Jeff King wrote:
Show 14 quoted lines
> Many other commands use the "no arguments" form to show a
> list (e.g., git-branch, git-tag). While we did show all
> remotes for just "git remote", we displayed a usage error
> for "git remote show" with no arguments. This is
> counterintuitive, since by giving it _more_ information, we
> get _less_ result.
> 
> The usage model can now be thought of as:
> 
>   - "git remote show <remote>": show a remote
>   - "git remote show": show all remotes
>   - "git remote": assume "show"; i.e., shorthand for "git remote show"
> 
> Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

Ciao, Dscho

Ingo Molnar· Apr 9, 2008, 20:07 UTC · re: Jeff King · lore

Re: [PATCH] git-remote: show all remotes with "git remote show"

* Jeff King <peff@peff.net> wrote:
Show 14 quoted lines
> Many other commands use the "no arguments" form to show a
> list (e.g., git-branch, git-tag). While we did show all
> remotes for just "git remote", we displayed a usage error
> for "git remote show" with no arguments. This is
> counterintuitive, since by giving it _more_ information, we
> get _less_ result.
> 
> The usage model can now be thought of as:
> 
>   - "git remote show <remote>": show a remote
>   - "git remote show": show all remotes
>   - "git remote": assume "show"; i.e., shorthand for "git remote show"
> 
> Signed-off-by: Jeff King <peff@peff.net>
cool, thanks!
	Ingo
Ingo Molnar· Apr 10, 2008, 19:59 UTC · re: Jeff King · lore

Re: [PATCH] git-remote: show all remotes with "git remote show"

* Jeff King <peff@peff.net> wrote:
Show 12 quoted lines
> Many other commands use the "no arguments" form to show a
> list (e.g., git-branch, git-tag). While we did show all
> remotes for just "git remote", we displayed a usage error
> for "git remote show" with no arguments. This is
> counterintuitive, since by giving it _more_ information, we
> get _less_ result.
> 
> The usage model can now be thought of as:
> 
>   - "git remote show <remote>": show a remote
>   - "git remote show": show all remotes
>   - "git remote": assume "show"; i.e., shorthand for "git remote show"

btw., another suggestion: because i use 'git-remote show' rather frequently, i recently typoed "git-bisect show" and then realized that it was "git-bisect visualize". Shouldnt there be a "git-bisect show" alias?

I think using 'show' for all such 'display state' things would be rather intuitive, if it was applied consistently all across the board. ('visualize' could still remain indefinitely, for compatibility - and 'git-bisect log' would still do the log of the bisection decisions that were entered.)

Or is there some purpose behind this deviation that i missed?
	Ingo
Avery Pennarun· Apr 9, 2008, 17:08 UTC · re: Jeff King · lore

Re: git annoyances

On Wed, Apr 9, 2008 at 10:57 AM, Jeff King <peff@peff.net> wrote:
>  >  $ git-fetch x86/latest
[...]
>   git-fetch <options> <repository> <refspec>
[...]
>  >  $ git-pull x86 latest
[...]
>   git pull ~/linux-2.6-x86.git latest

My co-workers frequently get confused by this too. The problem is that "x86/latest" is a locally existing remote branch ref, while "x86 latest" is supposed to be a branch ref on a remote system.

I think the real problem here is that you can't refer to a remote+branch as a single "word". If you could, then people could just learn to use that everywhere and never get confused.

For example, in svn you can talk about svn+ssh://reposerver/path/to/repo/branches/foo@1234; it's a single "word" that refers to a particular revision on a particular branch of a particular server. It therefore makes sense to talk about copying from one branch to another, etc, using exactly one word for the source and one for the destination.

Imagine if "git pull ~/linux/2.6-x86.git:latest" would work; then it could mean exactly the same thing as "git merge ~/linux/2.6-x86.git:latest" (which would presumably switch to 'pull' mode automatically). Or even "git diff master..x86:latest", which could diff my local master with an auto-fetched x86:latest.

Naturally we'd have to find a new punctuation mark for this, since all the obvious ones are already used :)

Have fun,
Avery
Karl Hasselström· Apr 10, 2008, 08:41 UTC · re: Avery Pennarun · lore

Re: git annoyances

On 2008-04-09 13:08:39 -0400, Avery Pennarun wrote:
> For example, in svn you can talk about
> svn+ssh://reposerver/path/to/repo/branches/foo@1234; it's a single
> "word" that refers to a particular revision on a particular branch
> of a particular server.

Heh, not really. Subversion actually makes this even more confusing than git does.

The @rev is called a "peg revision", and is different from the "operative revision" specified with the -r flag. The peg revision is used in conjunction with a path to specify the file (or directory) you want, and the operative revision is used to specify which revision of that file you mean. (This complexity is needed because subversion has a concept of file identity.)

So
  $ svn cp -r 4711 $REPO/foo@1234 somewhere-else

means "find the file (or directory) that was called 'foo' in revision 1234, then copy revision 4711 of that file to somewhere-else".

See http://svnbook.red-bean.com/en/1.4/svn.advanced.pegrevs.html for the full story.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle
Avery Pennarun· Apr 10, 2008, 15:05 UTC · re: Karl Hasselström · lore

Re: git annoyances

On Thu, Apr 10, 2008 at 4:41 AM, Karl Hasselström <kha@treskal.com> wrote:
Show 15 quoted lines
> On 2008-04-09 13:08:39 -0400, Avery Pennarun wrote:
>
>  > For example, in svn you can talk about
>  > svn+ssh://reposerver/path/to/repo/branches/foo@1234; it's a single
>  > "word" that refers to a particular revision on a particular branch
>  > of a particular server.
>
>  Heh, not really. Subversion actually makes this even more confusing
>  than git does.
>
>  The @rev is called a "peg revision", and is different from the
>  "operative revision" specified with the -r flag. The peg revision is
>  used in conjunction with a path to specify the file (or directory) you
>  want, and the operative revision is used to specify which revision of
>  that file you mean.
Yes, but I believe you get the one from @rev if you don't specify -r.

For example, I can ask for an "svn diff svn://blahblah@56 svn://blahblah@59" and it'll feed it to me as expected.

This is nearly the same as "svn diff -r56:59 svn://blahblah", except that it might look for blahblah in different places, as you say. I tend to prefer the @notation for exactly at that reason.

> (This complexity is needed because subversion has
>  a concept of file identity.)

File renames make diffing and merging complicated no matter whether you track them or not.

svn's tracking of file identity is additional, but doesn't increase the (UI) complexity in the common case. At least with svn, a newbie can even get real work done without even knowing about -r *or* @notation.

Compare that to arbitrary differences in behaviour between "git-fetch" vs "git-fetch a" vs "git-fetch a b", or the difference between HEAD^ and HEAD~1 and HEAD@1. git is very powerful, but also definitely more complex for beginners.

Have fun,
Avery
Karl Hasselström· Apr 11, 2008, 07:00 UTC · re: Avery Pennarun · lore

Re: git annoyances

On 2008-04-10 11:05:07 -0400, Avery Pennarun wrote:
Show 13 quoted lines
> On Thu, Apr 10, 2008 at 4:41 AM, Karl Hasselström <kha@treskal.com> wrote:
>
> > The @rev is called a "peg revision", and is different from the
> > "operative revision" specified with the -r flag. The peg revision
> > is used in conjunction with a path to specify the file (or
> > directory) you want, and the operative revision is used to specify
> > which revision of that file you mean.
>
> Yes, but I believe you get the one from @rev if you don't specify
> -r.
>
> For example, I can ask for an "svn diff svn://blahblah@56
> svn://blahblah@59" and it'll feed it to me as expected.
Ah, I didn't know that. But the URL I threw at you agrees:
Show 5 quoted lines
> Note that even when you don't explicitly supply a peg revision or
> operative revision, they are still present. For your convenience,
> the default peg revision is BASE for working copy items and HEAD for
> repository URLs. And when no operative revision is provided, it
> defaults to being the same revision as the peg revision.

Clearly, I need to use Subversion more, and not fool around with git all the time. :-)

Show 10 quoted lines
> > (This complexity is needed because subversion has a concept of
> > file identity.)
>
> File renames make diffing and merging complicated no matter whether
> you track them or not.
>
> svn's tracking of file identity is additional, but doesn't increase
> the (UI) complexity in the common case. At least with svn, a newbie
> can even get real work done without even knowing about -r *or*
> @notation.

I don't quite agree with you here. Subversion stores extra state, and that state needs to be considered (in the general case) when predicting what Subversion will do. There are a large number of simple cases where the user doesn't have to care, as you say, but every so often there's a case that's not so simple, and in those cases I _really_ prefer git's data model to Subversion's.

> Compare that to arbitrary differences in behaviour between
> "git-fetch" vs "git-fetch a" vs "git-fetch a b", or the difference
> between HEAD^ and HEAD~1 and HEAD@1. git is very powerful, but also
> definitely more complex for beginners.

Oh, I'm not arguing on that point. I like git because it's beutiful on the _inside_.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle
Teemu Likonen· Apr 9, 2008, 20:08 UTC · re: Jeff King · lore

Friendly refspecs (Was: Re: git annoyances)

Jeff King wrote (2008-04-09 10:57 -0400):
>   git-fetch <options> <repository> <refspec>

I have found this refs/heads/*:refs/remotes/* stuff quite confusing, but I'm starting to understand them. I know my way with them but still they seem quite unnecessary hackerish. Pull and push work pretty nicely without knowing about any refs/* stuff; they can be operated with simple branch names. Fetch is another story. Some ideas:

  $ git fetch <URL>
would be equivalent to
  $ git fetch <URL> +refs/heads/*:refs/remotes/<name>/*

In other words, fetch all the branches from remote repo and store them locally as remote tracking branches to <name>/ hieararchy. The <name> is the last component taken from the <URL> (maybe "origin" if it can't be detected).

Currently "git fetch <URL>" does not seem to do anything useful for non-git-hackers. It seems to fetch objects but not create any branches referring to them. As a comparison, let's configure a remote and run similar fetch command without any refspecs explicitly named:

  $ git remote add <name> <URL>
  $ git fetch <name>

Now this fetch really creates all the branches (as defined in remote.<name>.fetch) which is nice and the way Git currently works.

So would it be any good if "git fetch <URL>" without refpecs would use +refs/heads/*:refs/remotes/<name>/* ? In any case the current behaviour seems quite unfriendly.

Some more ideas for simple refspecs:
  $ git fetch <URL|name> <branch>
would be equivalent to
  $ git fetch <URL|name> +refs/heads/<branch>:refs/remotes/<name>/<branch>

Again the same behaviour with <URL> and configured remote <name>. In the <URL> case the <name> is the last component of the <URL>.

  $ git fetch <URL|name> <Rbranch>:<Lbranch>
would be equivalent to
  $ git fetch <URL|name> +refs/heads/<Rbranch>:refs/remotes/<Lbranch>

Note that by giving the destination branch (the right side of colon) the new remote tracking branch would be created directly to the refs/remotes/ hierarchy, not to refs/remotes/<name>/ hierarchy like in previous examples. This lets user a bit more control as she decided to give <Lbranch> explicitly. User may want to give refspec master:<name>/master to have new branch created as refs/remotes/<name>/master.

With above example commands it is not possible to fetch remote branches and store refs locally to refs/heads/ hierarchy. For this it would either need another step - "git branch my-branch <name>/master" - or use the long refspec form with fetch: +refs/heads/master:refs/heads/my-branch .

Does this sound any good?
Avery Pennarun· Apr 9, 2008, 20:32 UTC · re: Teemu Likonen · lore

Re: Friendly refspecs (Was: Re: git annoyances)

On Wed, Apr 9, 2008 at 4:08 PM, Teemu Likonen <tlikonen@iki.fi> wrote:
>  So would it be any good if "git fetch <URL>" without refpecs would use
>  +refs/heads/*:refs/remotes/<name>/* ? In any case the current behaviour
>  seems quite unfriendly.

But what should <name> be if you didn't provide it by doing git-remote-add? I think the lack of an obvious name for them is exactly why the branch names don't get created automatically.

Avery
Jeff King· Apr 9, 2008, 20:34 UTC · re: Teemu Likonen · lore

Re: Friendly refspecs (Was: Re: git annoyances)

On Wed, Apr 09, 2008 at 11:08:36PM +0300, Teemu Likonen wrote:
Show 14 quoted lines
> seem quite unnecessary hackerish. Pull and push work pretty nicely
> without knowing about any refs/* stuff; they can be operated with simple
> branch names. Fetch is another story. Some ideas:
> 
>   $ git fetch <URL>
> 
> would be equivalent to
> 
>   $ git fetch <URL> +refs/heads/*:refs/remotes/<name>/*
> 
> In other words, fetch all the branches from remote repo and store them
> locally as remote tracking branches to <name>/ hieararchy. The <name> is
> the last component taken from the <URL> (maybe "origin" if it can't be
> detected).

This has been discussed before and rejected, because the point of doing a fetch of a URL (rather than a remote name) is to do a "one-off" thing. IOW, you don't _want_ the tracking branches, as they will just clutter your branch space (plus choosing the last component is a bad heuristic; lots of people must ask Linus to pull from their .../linux-2.6 repository).

Almost nobody says "git fetch <URL>"; it is just a subpart of "git pull <URL>" which is intended for one-off merges (i.e., you are not tracking somebody over the long term, you just want to grab their work and merge it).

> Currently "git fetch <URL>" does not seem to do anything useful for
> non-git-hackers. It seems to fetch objects but not create any branches
> referring to them. As a comparison, let's configure a remote and run

It does; it puts the refs into FETCH_HEAD. Maybe a status table like the usual one would be more informative, like:

  From git://host/path/to/repo
   * [new branch]      foo -> FETCH_HEAD

though again, it would help if we could see a workflow that uses "git fetch <URL>" for something. I think the simplest answer in your case is "don't use git fetch <URL>".

Show 7 quoted lines
> similar fetch command without any refspecs explicitly named:
> 
>   $ git remote add <name> <URL>
>   $ git fetch <name>
> 
> Now this fetch really creates all the branches (as defined in
> remote.<name>.fetch) which is nice and the way Git currently works.

Sure. There is an explicit design decision that "because you gave this thing a nickname, you are probably interested in keeping its tracking branches around."

Show 7 quoted lines
> Some more ideas for simple refspecs:
> 
>   $ git fetch <URL|name> <branch>
> 
> would be equivalent to
> 
>   $ git fetch <URL|name> +refs/heads/<branch>:refs/remotes/<name>/<branch>

It would probably be nice if "git fetch name foo" saved the remote tracking branch remotes/name/foo, which it doesn't currently. But whether to do it with a URL is orthogonal; it depends on whether we use tracking branches for URLs in general, as you suggested above.

Show 5 quoted lines
>   $ git fetch <URL|name> <Rbranch>:<Lbranch>
> 
> would be equivalent to
> 
>   $ git fetch <URL|name> +refs/heads/<Rbranch>:refs/remotes/<Lbranch>
We almost have that. It's actually spelled:
  git fetch <URL|name> <Rbranch>:remotes/<Lbranch>

But again, what is the workflow? There are generally two ways of fetching:

  1. I am tracking some remote with multiple branches. I give it a
     remote name (either by editing the config file or by using
     git-remote). When i want to get updates, I do "git fetch <name>",
     and then I can work with the <name>/* branches as I want (diffing,
     merging, etc).
  2. "Somehow" I found out about something interesting in a particular
     branch of a particular repo. I want to pull that in to see the
     work, so I use "git pull <repo> <branch>". Alternatively, if I
     prefer to fetch and examine before pulling (even though the merge
     can of course be cancelled easily), I can "git fetch <repo>
     <branch>", followed by "git diff HEAD FETCH_HEAD", followed by "git
     merge FETCH_HEAD".

It seems like you are getting caught up on using "git fetch" in different ways that don't really make sense to its original use. So the problem is not so much one of "fetch doesn't do what I want it to do" as much as "it is easy to be confused about what it is I want to do."

-Peff
Teemu Likonen· Apr 9, 2008, 22:25 UTC · re: Jeff King · lore

Re: Friendly refspecs (Was: Re: git annoyances)

Jeff King wrote (2008-04-09 16:34 -0400):
> On Wed, Apr 09, 2008 at 11:08:36PM +0300, Teemu Likonen wrote:
Show 5 quoted lines
> >   $ git fetch <URL>
> > 
> > would be equivalent to
> > 
> >   $ git fetch <URL> +refs/heads/*:refs/remotes/<name>/*
> This has been discussed before and rejected, because the point of
> doing a fetch of a URL (rather than a remote name) is to do
> a "one-off" thing.

First, thank you for such a detailed information and giving somewhat different point of view from mine.

Ok, "git fetch <URL>" has its own "point", as you noted, and no doubt it's for good reasons. I just had partially misunderstood its point. See below:

> Almost nobody says "git fetch <URL>"; it is just a subpart of "git
> pull <URL>" [...]

Hmm, maybe. I recently wanted to join two purely local repos together. Both of them had just one branch. Totally different histories so no actual mergin would happen; just two branches in the same repo. I don't know why but "git fetch /the/other/repo/" just happened to be the one I tried first. I saw it fetched something but as no new branch appeared and I had never heard of this FETCH_HEAD thing it was a "didn't work, what should I try next?" thing. I think your idea of showing

>   From git://host/path/to/repo
>    * [new branch]      foo -> FETCH_HEAD

would be really good. At least to me this would have been enough information. As I'm starting to see the "point of doing fetch <URL>" I take back what I proposed. Just a bit more information would be nice.

I have to agree with Ingo Molnar that sometimes Git is a bit un- or even disinformative about what happened. One example is this "git fetch <URL>". Maybe it's not a "sane thing to do" but users are like this. We just try something and learn from it. To me "git fetch <URL>" was a broken command (UI-wise) until I read your message (thanks again!). If Git had told me that it created FETCH_HEAD I had learned fetch's habits myself and likely wouldn't have come up with this "broken command" conclusion.

Another thing I spoke of was this refs/ stuff. I know my way around with them now, so maybe they are not actually confusing to me anymore. It's just that I have noticed a pattern: I always use refs/heads/... in certain places and refs/remotes/ in certain places. If such a pattern is very common (well, I don't know if it is) one starts to think that maybe the pattern can/should be hidden and made part of the tool. Just thoughts.

Jeff King· Apr 9, 2008, 22:51 UTC · re: Teemu Likonen · lore

Re: Friendly refspecs (Was: Re: git annoyances)

On Thu, Apr 10, 2008 at 01:25:00AM +0300, Teemu Likonen wrote:
Show 7 quoted lines
> Hmm, maybe. I recently wanted to join two purely local repos together.
> Both of them had just one branch. Totally different histories so no
> actual mergin would happen; just two branches in the same repo. I don't
> know why but "git fetch /the/other/repo/" just happened to be the one
> I tried first. I saw it fetched something but as no new branch appeared
> and I had never heard of this FETCH_HEAD thing it was a "didn't work,
> what should I try next?" thing. I think your idea of showing

Ah, OK. In that case, I think the right thing to do would not be to set up a remote, but to fetch explicitly into a local branch. I assume when you say "joining" you mean "so I can get rid of the individual ones". So something like:

  cd repo1
  git fetch ../repo2 master:repo2-topic

which creates refs/heads/repo2 in repo1, and you can safely delete repo2.

If you _did_ want to keep repo2 around indefinitely, and you are "joining" so that you can do diffs, then you probably do want a remote with tracking branches.

  cd repo1
  git remote add repo2 ../repo2
  git fetch repo2
  git diff repo2/master...master
Show 6 quoted lines
> >   From git://host/path/to/repo
> >    * [new branch]      foo -> FETCH_HEAD
> 
> would be really good. At least to me this would have been enough
> information. As I'm starting to see the "point of doing fetch <URL>"
> I take back what I proposed. Just a bit more information would be nice.

I wonder if people like Linus who do a lot of one-off pulls would find that too cluttery. I guess we can post a patch and see. ;)

Show 8 quoted lines
> I have to agree with Ingo Molnar that sometimes Git is a bit un- or even
> disinformative about what happened. One example is this "git fetch
> <URL>". Maybe it's not a "sane thing to do" but users are like this. We
> just try something and learn from it. To me "git fetch <URL>" was
> a broken command (UI-wise) until I read your message (thanks again!). If
> Git had told me that it created FETCH_HEAD I had learned fetch's habits
> myself and likely wouldn't have come up with this "broken command"
> conclusion.

Sure. In my other message I talked about workflows not to imply "how dare you explore the commands!" but rather to see where you were coming from. I agree that a lot of git messages could be improved. So I think the take-away lesson is not that there needs to be some huge change in behavior or what input is accepted, but that git-fetch without tracking branches should probably give a clue that it did _something_.

Show 7 quoted lines
> Another thing I spoke of was this refs/ stuff. I know my way around with
> them now, so maybe they are not actually confusing to me anymore. It's
> just that I have noticed a pattern: I always use refs/heads/... in
> certain places and refs/remotes/ in certain places. If such a pattern is
> very common (well, I don't know if it is) one starts to think that maybe
> the pattern can/should be hidden and made part of the tool. Just
> thoughts.

I almost never use refs/remotes/ or refs/heads/. Some effort has been put into doing the right thing with partial refnames (which you can of course override by being more specific). Do you have specific examples of where you use the full refname? I suspect it is either not required (and documentation may be out of date), or it is a bug we could fix. :)

-Peff
Jeff King· Apr 10, 2008, 00:03 UTC · re: Jeff King · lore

Re: Friendly refspecs (Was: Re: git annoyances)

On Wed, Apr 09, 2008 at 06:51:12PM -0400, Jeff King wrote:
> > >   From git://host/path/to/repo
> > >    * [new branch]      foo -> FETCH_HEAD
As it turns out, there is already code to do this very thing, but:
  1. it was broken ;)
  2. you need to specify "-v"erbose mode to see it

Here is a patch that fixes the breakage, which should be done either way. If people think this is a good thing to show in general (and I do, but then I am not a very frequent user of "fetch without tracking branches"), then there is an obvious one-liner to make it always show.

-- >8 -- git-fetch: fix status output when not storing tracking ref

There was code in update_local_ref for handling this case, but it never actually got called. It assumed that storing in FETCH_HEAD meant a blank peer_ref name, but we actually have a NULL peer_ref in this case, so we never even made it to the update_local_ref function.

On top of that, the display formatting was different from all of the other cases, probably owing to the fact that nobody had ever actually seen the output.

This patch harmonizes the output with the other cases and moves the detection of this case into store_updated_refs, where we can actually trigger it.

Signed-off-by: Jeff King <peff@peff.net>
---
 builtin-fetch.c |   28 +++++++++++++---------------
 1 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 5841b3e..139a6b1 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -215,13 +215,6 @@ static int update_local_ref(struct ref *ref,
 	if (type < 0)
 		die("object %s not found", sha1_to_hex(ref->new_sha1));
 
-	if (!*ref->name) {
-		/* Not storing */
-		if (verbose)
-			sprintf(display, "* branch %s -> FETCH_HEAD", remote);
-		return 0;
-	}
-
 	if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
 		if (verbose)
 			sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH,
@@ -365,16 +358,21 @@ static int store_updated_refs(const char *url, struct ref *ref_map)
 			rm->merge ? "" : "not-for-merge",
 			note);
 
-		if (ref) {
+		if (ref)
 			update_local_ref(ref, what, verbose, note);
-			if (*note) {
-				if (!shown_url) {
-					fprintf(stderr, "From %.*s\n",
-							url_len, url);
-					shown_url = 1;
-				}
-				fprintf(stderr, " %s\n", note);
+		else if (verbose)
+			sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
+				SUMMARY_WIDTH, *kind ? kind : "branch",
+				 REFCOL_WIDTH, *what ? what : "HEAD");
+		else
+			*note = '\0';
+		if (*note) {
+			if (!shown_url) {
+				fprintf(stderr, "From %.*s\n",
+						url_len, url);
+				shown_url = 1;
 			}
+			fprintf(stderr, " %s\n", note);
 		}
 	}
 	fclose(fp);
-- 
1.5.5.25.g43bd4.dirty
Jeff King· Apr 10, 2008, 00:11 UTC · re: Jeff King · lore

Re: Friendly refspecs (Was: Re: git annoyances)

On Wed, Apr 09, 2008 at 08:03:49PM -0400, Jeff King wrote:
> Here is a patch that fixes the breakage, which should be done either
> way. If people think this is a good thing to show in general (and I do,
> but then I am not a very frequent user of "fetch without tracking
> branches"), then there is an obvious one-liner to make it always show.

And here is that one-liner, in case there is interest. The only negative I can think of is that git-pull will now produce two extra lines of output mentioning FETCH_HEAD (which I actually think is a positive, but I can see that people might consider it clutter).

-- >8 -- git-fetch: always show status of non-tracking-ref fetches

Previously, a fetch like:
  git fetch git://some/url

would show no ref status output (just the object downloading status, if there was any), leading to some confusion.

With this patch, we now show the usual ref table, with remote refs going into FETCH_HEAD. Previously this output was shown only if "-v"erbose was specified.

Signed-off-by: Jeff King <peff@peff.net>
---
 builtin-fetch.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 139a6b1..e4486e4 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -360,12 +360,10 @@ static int store_updated_refs(const char *url, struct ref *ref_map)
 
 		if (ref)
 			update_local_ref(ref, what, verbose, note);
-		else if (verbose)
+		else
 			sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
 				SUMMARY_WIDTH, *kind ? kind : "branch",
 				 REFCOL_WIDTH, *what ? what : "HEAD");
-		else
-			*note = '\0';
 		if (*note) {
 			if (!shown_url) {
 				fprintf(stderr, "From %.*s\n",
-- 
1.5.5.26.g8c565.dirty
Junio C Hamano· Apr 10, 2008, 07:51 UTC · re: Jeff King · lore

Re: Friendly refspecs

Thanks for bringing this issue up and proposing a pair of improvements.

I am very inclined to apply [1/2] to maint. I am not convinced if [2/2] is a good idea in general but if it is silent on pull and verbose on one-off fetch without local store, it probably is an improvement.

Jeff King· Apr 10, 2008, 08:03 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Thu, Apr 10, 2008 at 12:51:08AM -0700, Junio C Hamano wrote:
Show 5 quoted lines
> Thanks for bringing this issue up and proposing a pair of improvements.
> 
> I am very inclined to apply [1/2] to maint.  I am not convinced if [2/2]
> is a good idea in general but if it is silent on pull and verbose on
> one-off fetch without local store, it probably is an improvement.

I think that is the right behavior for 2/2; I was just being a little lazy earlier. I will try to work up an improved 2/2, but I will probably be out of touch for a few days. Maybe we will see some comments from the list in the meantime.

-Peff
Teemu Likonen· Apr 13, 2008, 09:31 UTC · re: Jeff King · lore

Re: Friendly refspecs

Jeff King wrote (2008-04-09 18:51 -0400):
Show 16 quoted lines
> On Thu, Apr 10, 2008 at 01:25:00AM +0300, Teemu Likonen wrote:
> 
> > Another thing I spoke of was this refs/ stuff. I know my way around
> > with them now, so maybe they are not actually confusing to me
> > anymore. It's just that I have noticed a pattern: I always use
> > refs/heads/... in certain places and refs/remotes/ in certain
> > places. If such a pattern is very common (well, I don't know if it
> > is) one starts to think that maybe the pattern can/should be hidden
> > and made part of the tool. Just thoughts.
> 
> I almost never use refs/remotes/ or refs/heads/. Some effort has been
> put into doing the right thing with partial refnames (which you can of
> course override by being more specific). Do you have specific examples
> of where you use the full refname? I suspect it is either not required
> (and documentation may be out of date), or it is a bug we could fix.
> :)

In real work I have used refs/heads/...:refs/remotes/... only once or maybe twice (I just quite recently started using Git). But when I studied Git and the workflows it supports I tried all kinds of fetching, pulling and pushing, back and forth, between test repos. There I used refs/ paths a lot, almost all the time actually. At first it was very much just trying to see how they work and this is where I found this common pattern: local refs start with refs/heads/ and remote tracking ones with refs/remotes/ . Thoughts like "why not simplify them, like L: for local and R: for remote" (or something) started to develop.

Now it seems that I have been too much attached to the full refspec form. My guide have been the config remote.<name>.fetch as "git remote add" adds those long refspecs. Now I learnt that almost all refspecs can be written as "branch:another" or "branch:remotes/another" for example. So the "friendly refspecs" are pretty much already there! Well, I've been stupid. :)

(I understand that in real work when constantly dealing with same remote repos one just adds a remote config and can forget about URLs and probably most of the refspecs too.)

Ok, this was partly an RTFM error but even after reading man pages of fetch, pull and push it isn't quite clear how to use these short and nice and friendly refspecs. I thought about it and decided to add some more examples to fetch manual (see my patch in the next message). My English may not be manual-writing quality but I wanted to do something useful anyway. Somebody needs to proof read my text though. Of course there may be some inaccuracies too. Anyway, I think that concrete examples in manuals help people to understand Git better.

There is still one thing (at least) that I don't quite understand. It's about "git push". When I do

  $ git push <remote> <branch>

the refs/heads/<branch> is updated or created on the remote side. But if I do

  $ git push <remote> <branch1>:<branch2>

the refs/heads/<branch2> is not automatically created. Why there is need to say "<branch1>:refs/heads/<branch2>" to make it work if <branch2> does not exist? The 'git push' manual says something vague about branch not matching (?). What does it mean?

Teemu Likonen· Apr 13, 2008, 09:34 UTC · re: Teemu Likonen · lore

[PATCH] Add examples section to 'git fetch' manual

This commit adds examples which intend to cover the various ways of using 'git fetch'.

Signed-off-by: Teemu Likonen <tlikonen@iki.fi>
---
 Documentation/git-fetch.txt |   43 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 42 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index d982f96..d5b1c9f 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -37,9 +37,50 @@ include::pull-fetch-param.txt[]
 
 include::urls-remotes.txt[]
 
+EXAMPLES
+--------
+
+git fetch git://host.xz/repo.git/ master:pu::
+	Fetch branch `master` from given repository URL and store it locally
+	as `pu`.
+
+git fetch git://host.xz/repo.git/ master:remotes/pu::
+	Fetch branch `master` from given repository URL and store it locally as
+	remote tracking branch `pu`.
+
+git fetch git://host.xz/repo.git/ master::
+	Fetch branch `master` from given repository URL but do not create the
+	branch locally. Only the temporary pointer FETCH_HEAD is set to refer
+	to the fetched branch.
+
+git fetch /home/bob/tmp/repo.git::
+	Fetch the currently active branch from given local repository and set
+	the temporary pointer FETCH_HEAD for the fetched branch.
+
+git fetch alice master:remotes/alice/pu::
+	Fetch branch `master` from remote named `alice` and store it locally as
+	remote tracking branch `alice/pu`. See linkgit:git-remote[1] for more
+	information on configuring remotes.
+
+git fetch alice +master:remotes/alice/pu::
+	The same as above but the remote tracking branch `alice/pu` is updated
+	even if it does not result in a fast forward update.
+
+git fetch alice +master:pu maint:tmp::
+	Fetch branches `master` and `maint` from remote named `alice` and store
+	them locally as `pu` and `tmp` respectively. The branch `pu` is updated
+	even if it does not result in a fast forward update.
+
+git fetch origin::
+	From the remote named `origin` fetch and store all branches as
+	configured in `remote.origin.fetch`. Usually this means fetching all
+	branches and storing them locally as remote tracking branches
+	`origin/*`. See linkgit:git-remote[1] for more information.
+
+
 SEE ALSO
 --------
-linkgit:git-pull[1]
+linkgit:git-pull[1], linkgit:git-remote[1]
 
 
 Author
-- 
1.5.5.32.g5279
Junio C Hamano· Apr 13, 2008, 18:56 UTC · re: Teemu Likonen · lore

Re: [PATCH] Add examples section to 'git fetch' manual

Teemu Likonen <tlikonen@iki.fi> writes:
Show 6 quoted lines
> +EXAMPLES
> +--------
> +
> +git fetch git://host.xz/repo.git/ master:pu::
> +	Fetch branch `master` from given repository URL and store it locally
> +	as `pu`.

While this may technically be correct (and I'll say upfront that all of your "examples" may technically be correct), I would suggest strongly against putting this into EXAMPLES section. People look at examples section to look up something they need to do often; the section should describe the best practices we can suggest them in real life.

The above command line is a _great_ way to explain what happens under the hood when you have the matching configuration in .git/config for the remote, so that people would know how to update .git/config entries from what git-clone and "git-remote add" give them by default to suit their needs (e.g. instead of storing all branches in remotes/origin/*, you can configure to only fetch and store a few selected branches). But, fetching from somewhere and storing it explicitly _from the command line_ like your example command line is something you would _never_ do in real life if you know git.

> +git fetch git://host.xz/repo.git/ master:remotes/pu::
> +	Fetch branch `master` from given repository URL and store it locally as
> +	remote tracking branch `pu`.

And this example is even worse, as the common example is to have remote name between "remotes" and "pu".

> +git fetch git://host.xz/repo.git/ master::
> +	Fetch branch `master` from given repository URL but do not create the
> +	branch locally. Only the temporary pointer FETCH_HEAD is set to refer
> +	to the fetched branch.

This one is a fine example of a one-shot command to look at what they have without actually affecting your own history. Use of this form in real life is very sane.

> +git fetch alice master:remotes/alice/pu::
> +	Fetch branch `master` from remote named `alice` and store it locally as
> +	remote tracking branch `alice/pu`. See linkgit:git-remote[1] for more
> +	information on configuring remotes.

This is a wrong example on multiple counts (this is one of the worst one in your change, so I'll explain in more detail than for others).

First of all, think about the reason _why_ the convention is to use a separate namespace under remotes/ per remote. It is to allow us to use the names that correspond to what the remote repository uses without having to worry about name collisions, and the reason we took pains to implement the mechanism to allow you to use such corresponding names is to avoid having to remember "what she calls master is what I call pu".

"I want to make sure I can tell my master and her master apart without confusing myself, so I'd call mine master and call hers alice/master" is the recommended use pattern which "git clone" and "git remote add" give the user. An EXAMPLE that deviates from it without explaining why/when it is a good thing to do is BAD. Remember, many people blindly copy and paste the examples section without thinking, assuming that they suggest the best practice.

If you have nickname "alice" defined, you are by definition interacting with her regularly. If you are doing a one-off with such a repository, running "git fetch alice master" and operating on the resulting FETCH_HEAD (and you typically use tag or local branch if you want to mark that commit, with "git tag" or "git branch"), would be much less error prone, less confusing, and more straightforward recommended approach. Typically, you would have the usual refs/heads/*:refs/remotes/alice/* fetch refspec, so you would not even say "master" and instead run "git fetch alice" and look at "remotes/alice/master".

Your above command line again may be a great way to explain what you could do and what the mechanism is equipped to allow you to, but I do not think there is any reason to use it in the real life. It should not be in the EXAMPLE section.

Show 5 quoted lines
> +git fetch origin::
> +	From the remote named `origin` fetch and store all branches as
> +	configured in `remote.origin.fetch`. Usually this means fetching all
> +	branches and storing them locally as remote tracking branches
> +	`origin/*`. See linkgit:git-remote[1] for more information.

This is a valid thing to add to the examples section, although I suspect people would already know it when they encouter this page.

Matt Graham· Apr 13, 2008, 19:48 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add examples section to 'git fetch' manual

On Sun, Apr 13, 2008 at 2:56 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 10 quoted lines
> Teemu Likonen <tlikonen@iki.fi> writes:
>
>  > +git fetch origin::
>  > +     From the remote named `origin` fetch and store all branches as
>  > +     configured in `remote.origin.fetch`. Usually this means fetching all
>  > +     branches and storing them locally as remote tracking branches
>  > +     `origin/*`. See linkgit:git-remote[1] for more information.
>
>  This is a valid thing to add to the examples section, although I suspect
>  people would already know it when they encouter this page.

As a recent CVS emigrant, I'm finding the refspecs one of the more confusing areas of git. I think having good, basic examples might be more helpful than experienced users expect. In my case at least, this is a helpful example.

Teemu Likonen· Apr 13, 2008, 20:05 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add examples section to 'git fetch' manual

Junio C Hamano wrote (2008-04-13 11:56 -0700):
> People look at examples section to look up something they need to do
> often; the section should describe the best practices we can suggest
> them in real life.

Thanks for your explanations, they made a lot of sense. I see, I gave examples of various ways of using "git fetch" but they may not reflect real life usage patterns very well. I still feel that refspecs need more explaining (for newbies, that is) so I may later bring another patch hopefully with better examples and applicable to real workflows.

Junio C Hamano· Apr 14, 2008, 01:02 UTC · re: Teemu Likonen · lore

Re: [PATCH] Add examples section to 'git fetch' manual

Teemu Likonen <tlikonen@iki.fi> writes:
> ... I still feel that refspecs need more
> explaining ...

Perhaps. The basic syntax is "src colon dst" and they are used to copy what's in src to dst, and that is pretty much what's there to it. Some details such as how the wildcard matching works may be missing from the description part of the manual, and filling them in would be a good idea.

I however strongly suspect that what new people need to get explained may not be what the mechanism does (e.g. copies the object name recorded as the src ref to the dst ref), nor the syntax you use to tell the mechanism what to copy where (e.g. src is LHS, dst is RHS, copying "emptyness" into dst means deleting dst). I actually think that is an easier part.

What is more important is the basic concepts like what a ref is, how they can be used and what you can do with them --- understanding of which would be essential in being able to decide when and how you maywant to keep a copy of ref you get from elsewhere and under what name. I think tutorial is the best place, and then the description section of the manual the second best one, to document that kind of things.

Jeff King· Apr 16, 2008, 03:48 UTC · re: Teemu Likonen · lore

Re: Friendly refspecs

On Sun, Apr 13, 2008 at 12:31:02PM +0300, Teemu Likonen wrote:
Show 14 quoted lines
> There is still one thing (at least) that I don't quite understand. It's
> about "git push". When I do
> 
>   $ git push <remote> <branch>
> 
> the refs/heads/<branch> is updated or created on the remote side. But if
> I do
> 
>   $ git push <remote> <branch1>:<branch2>
> 
> the refs/heads/<branch2> is not automatically created. Why there is need
> to say "<branch1>:refs/heads/<branch2>" to make it work if <branch2>
> does not exist? The 'git push' manual says something vague about branch
> not matching (?). What does it mean?

This happens because "git push <remote> <branch>" is expanded locally to "git push <remote> <branch>:<branch>", but <branch> is first expanded into refs/heads/<branch>.

The latter uses the explicit refspec <branch2> which doesn't get expanded, since it doesn't exist at all, and so we can't deduce the type (e.g., refs/heads versus refs/tags).

ISTR some discussion in the past few months about using the type of <branch1> to guess the type of <branch2>, but it seems not to have gone anywhere.

Daniel, were you working on this?
-Peff
Jeff King· Apr 16, 2008, 04:25 UTC · re: Jeff King · lore

Re: Friendly refspecs

On Tue, Apr 15, 2008 at 11:48:23PM -0400, Jeff King wrote:
Show 5 quoted lines
> ISTR some discussion in the past few months about using the type of
> <branch1> to guess the type of <branch2>, but it seems not to have gone
> anywhere.
> 
> Daniel, were you working on this?

Hmm. Here is a quick patch I worked up, but it causes t5516:14 (push with ambiguity) to fail. However, I'm not sure the test is right: it looks like it's trying to find ambiguity between remotes/origin/master and remotes/frotz/master, but in fact matches _neither_ of them. So it was failing before as we expected, but for the wrong reason.

---
 remote.c              |   23 +++++++++++++++++++----
 t/t5516-fetch-push.sh |    8 ++++++++
 2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/remote.c b/remote.c
index 08af7f9..2f5d062 100644
--- a/remote.c
+++ b/remote.c
@@ -851,10 +851,25 @@ static int match_explicit(struct ref *src, struct ref *dst,
 	case 0:
 		if (!memcmp(dst_value, "refs/", 5))
 			matched_dst = make_linked_ref(dst_value, dst_tail);
-		else
-			error("dst refspec %s does not match any "
-			      "existing ref on the remote and does "
-			      "not start with refs/.", dst_value);
+		else {
+			/*
+			 * We don't have a full ref name for the dst and
+			 * it doesn't exist, so let's assume it's the same
+			 * type as our src.
+			 */
+			struct strbuf tmp = STRBUF_INIT;
+			const char *c;
+			int slashes;
+			for (c = matched_src->name, slashes = 0;
+					*c && slashes < 2; c++) {
+				strbuf_addch(&tmp, *c);
+				if (*c == '/')
+					slashes++;
+			}
+			strbuf_addstr(&tmp, dst_value);
+			dst_value = strbuf_detach(&tmp, NULL);
+			matched_dst = make_linked_ref(dst_value, dst_tail);
+		}
 		break;
 	default:
 		matched_dst = NULL;
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 793ffc6..370f79a 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -285,6 +285,14 @@ test_expect_success 'push with colon-less refspec (4)' '
 
 '
 
+test_expect_success 'push with non-existant, incomplete dest' '
+
+	mk_test &&
+	git push testrepo master:brandnewbranch &&
+	check_push_result $the_commit heads/brandnewbranch
+
+'
+
 test_expect_success 'push with HEAD' '
 
 	mk_test heads/master &&
-- 
1.5.5.64.geecd2.dirty
Junio C Hamano· Apr 16, 2008, 04:41 UTC · re: Jeff King · lore

Re: Friendly refspecs

Jeff King <peff@peff.net> writes:
Show 13 quoted lines
> On Sun, Apr 13, 2008 at 12:31:02PM +0300, Teemu Likonen wrote:
>
>> There is still one thing (at least) that I don't quite understand. It's
>> about "git push". When I do
>> 
>>   $ git push <remote> <branch>
>> 
>> the refs/heads/<branch> is updated or created on the remote side. But if
>> I do
>> 
>>   $ git push <remote> <branch1>:<branch2>
>> 
>> the refs/heads/<branch2> is not automatically created.

Eh, there is no way unless you force an assumption of a particular workflow to everybody else.

What you would say on the second command is not literally "<branch2>" but something like "work-in-progress", or "crap". Even an AI would not be able to guess if you wanted to create a branch on the other side, or wanted to put a lightweight tag to let people know where you are (possibly with the intention of removing it once you are done), and git is not an AI.

Jeff King· Apr 16, 2008, 04:47 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Tue, Apr 15, 2008 at 09:41:17PM -0700, Junio C Hamano wrote:
Show 5 quoted lines
> What you would say on the second command is not literally "<branch2>" but
> something like "work-in-progress", or "crap".  Even an AI would not be
> able to guess if you wanted to create a branch on the other side, or
> wanted to put a lightweight tag to let people know where you are (possibly
> with the intention of removing it once you are done), and git is not an AI.

Of course it can't guess all cases. But right now you have the option of:

  1. specifying the full destination manually
  2. having git complain, and then doing (1)

I think changing (2) to "having git make a reasonable guess" is a better behavior. And I think it is a reasonable guess to use the _same_ type, just as we do with "git push <branch>".

-Peff
Daniel Barkalow· Apr 16, 2008, 15:42 UTC · re: Jeff King · lore

Re: Friendly refspecs

On Tue, 15 Apr 2008, Jeff King wrote:
Show 30 quoted lines
> On Sun, Apr 13, 2008 at 12:31:02PM +0300, Teemu Likonen wrote:
> 
> > There is still one thing (at least) that I don't quite understand. It's
> > about "git push". When I do
> > 
> >   $ git push <remote> <branch>
> > 
> > the refs/heads/<branch> is updated or created on the remote side. But if
> > I do
> > 
> >   $ git push <remote> <branch1>:<branch2>
> > 
> > the refs/heads/<branch2> is not automatically created. Why there is need
> > to say "<branch1>:refs/heads/<branch2>" to make it work if <branch2>
> > does not exist? The 'git push' manual says something vague about branch
> > not matching (?). What does it mean?
> 
> This happens because "git push <remote> <branch>" is expanded locally to
> "git push <remote> <branch>:<branch>", but <branch> is first expanded
> into refs/heads/<branch>.
> 
> The latter uses the explicit refspec <branch2> which doesn't get
> expanded, since it doesn't exist at all, and so we can't deduce the type
> (e.g., refs/heads versus refs/tags).
> 
> ISTR some discussion in the past few months about using the type of
> <branch1> to guess the type of <branch2>, but it seems not to have gone
> anywhere.
> 
> Daniel, were you working on this?

I was only working on making "HEAD" expand to HEAD:<current branch>. I think that the matching type is only most likely what you want, not certainly enough to just do it. I'd say that push should suggest it, but not actually do it automatically, or possibly require -f to do it without the full name.

	-Daniel
*This .sig left intentionally blank*
Junio C Hamano· Apr 16, 2008, 20:03 UTC · re: Daniel Barkalow · lore

Re: Friendly refspecs

Daniel Barkalow <barkalow@iabervon.org> writes:
Show 5 quoted lines
> I was only working on making "HEAD" expand to HEAD:<current branch>. I 
> think that the matching type is only most likely what you want, not 
> certainly enough to just do it. I'd say that push should suggest it, but 
> not actually do it automatically, or possibly require -f to do it without 
> the full name.

Hmm. `-f` means "I know there are the ones that do not fast forward but I want them updated", which is quite a different thing. I'd say either we should just do it, or we don't, and keep `-f` orthogonal to the ref dwimming.

Jeff King· Apr 22, 2008, 10:56 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Wed, Apr 16, 2008 at 01:03:22PM -0700, Junio C Hamano wrote:
Show 10 quoted lines
> > I was only working on making "HEAD" expand to HEAD:<current branch>. I 
> > think that the matching type is only most likely what you want, not 
> > certainly enough to just do it. I'd say that push should suggest it, but 
> > not actually do it automatically, or possibly require -f to do it without 
> > the full name.
> 
> Hmm.  `-f` means "I know there are the ones that do not fast forward but I
> want them updated", which is quite a different thing.  I'd say either we
> should just do it, or we don't, and keep `-f` orthogonal to the ref
> dwimming.

Hmm. I was kind of hoping other people would chime in with opinions on the dwimmery, but clearly they didn't.

I agree that "-f" is a terrible idea here. Not only is it overloading what "-f" does, but it's totally unnecessary. If we want to send a message to the user to retry with different parameters, we can already say: "try again with refs/heads/$foo".

The "refs/heads/" dwimmery makes sense to me, because:
  1. it changes a behavior which is currently an error condition, so
     we're not hurting anyone's existing workflow
  2. In my usage, pushing a branch to a tag (or vice versa) is the
     exception, so I don't mind favoring pushing like types to like
     types.

But I recognize that (2) is based on my own workflow, so if people disagree, I guess it isn't so for everyone.

We should probably at least improve the message. Something like this is perhaps a bit better, or it could even customize the suggestion based on the source ref's type (i.e., implement the dwimmery, but don't surprise anyone by doing it automatically).

-Peff
---
diff --git a/remote.c b/remote.c
index 06ad156..2151829 100644
--- a/remote.c
+++ b/remote.c
@@ -867,9 +867,12 @@ static int match_explicit(struct ref *src, struct ref *dst,
 		if (!memcmp(dst_value, "refs/", 5))
 			matched_dst = make_linked_ref(dst_value, dst_tail);
 		else
-			error("dst refspec %s does not match any "
-			      "existing ref on the remote and does "
-			      "not start with refs/.", dst_value);
+			error("The destination refspec does not match any "
+			      "existing ref on the remote,\n"
+			      "and it does not specify a full refname; "
+			      "did you mean one of:\n"
+			      "    refs/heads/%s\n"
+			      "    refs/tags/%s\n", dst_value, dst_value);
 		break;
 	default:
 		matched_dst = NULL;
Junio C Hamano· Apr 22, 2008, 16:52 UTC · re: Jeff King · lore

Re: Friendly refspecs

Jeff King <peff@peff.net> writes:
Show 11 quoted lines
> The "refs/heads/" dwimmery makes sense to me, because:
>
>   1. it changes a behavior which is currently an error condition, so
>      we're not hurting anyone's existing workflow
>
>   2. In my usage, pushing a branch to a tag (or vice versa) is the
>      exception, so I don't mind favoring pushing like types to like
>      types.
>
> But I recognize that (2) is based on my own workflow, so if people
> disagree, I guess it isn't so for everyone.
So the proposal is:
	"git push $there $commit:$name", when $name does not begin with
	refs/, is interpreted as "git push $there $commit:refs/heads/$name"
right?  I think that makes sense, at least to me.
Daniel Barkalow· Apr 22, 2008, 17:19 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Tue, 22 Apr 2008, Junio C Hamano wrote:
Show 20 quoted lines
> Jeff King <peff@peff.net> writes:
> 
> > The "refs/heads/" dwimmery makes sense to me, because:
> >
> >   1. it changes a behavior which is currently an error condition, so
> >      we're not hurting anyone's existing workflow
> >
> >   2. In my usage, pushing a branch to a tag (or vice versa) is the
> >      exception, so I don't mind favoring pushing like types to like
> >      types.
> >
> > But I recognize that (2) is based on my own workflow, so if people
> > disagree, I guess it isn't so for everyone.
> 
> So the proposal is:
> 
> 	"git push $there $commit:$name", when $name does not begin with
> 	refs/, is interpreted as "git push $there $commit:refs/heads/$name"
> 
> right?  I think that makes sense, at least to me.

That's no good for people who make lightweight tags, since those will be commits, and "git push <remote> tag:tag" would push refs/tags/tag to refs/heads/tag.

But I think the proposal was for "git push $there $name:$name", where name gets expanded locally to refs/heads/$name, which I think should probably work. I think it should require $name to be unambiguous locally, though, because it wouldn't be too unusual for people to end up with the same name for a branch and a lightweight tag, and then try pushing that name, expecting one or the other to get pushed.

	-Daniel
*This .sig left intentionally blank*
Jeff King· Apr 22, 2008, 20:12 UTC · re: Daniel Barkalow · lore

Re: Friendly refspecs

On Tue, Apr 22, 2008 at 01:19:35PM -0400, Daniel Barkalow wrote:
> That's no good for people who make lightweight tags, since those will be 
> commits, and "git push <remote> tag:tag" would push refs/tags/tag to 
> refs/heads/tag.
Yes.
Show 6 quoted lines
> But I think the proposal was for "git push $there $name:$name", where name 
> gets expanded locally to refs/heads/$name, which I think should probably 
> work. I think it should require $name to be unambiguous locally, though, 
> because it wouldn't be too unusual for people to end up with the same name 
> for a branch and a lightweight tag, and then try pushing that name, 
> expecting one or the other to get pushed.

Ambiguity is already handled when we resolve the left-hand side of the refspec:

  $ git branch foo
  $ git tag foo
  $ git push origin foo
  error: src refspec foo matches more than one.
  fatal: The remote end hung up unexpectedly
  error: failed to push some refs to '/home/peff/foo/parent/.git'
I guess you could say something like:
  $ git branch dest
  $ git tag dest
  $ git push origin master:dest

and the "dest" here will become a branch. But that is because it has nothing to do with your local refs called "dest": the right-hand side is purely a remote matter. If the remote has an ambiguous "dest", then we already handle that case:

  $ cd ../parent && git branch dest && git tag dest
  $ cd ../child && git push origin master:dest
  error: dst refspec dest matches more than one.
  fatal: The remote end hung up unexpectedly
  error: failed to push some refs to '/home/peff/foo/parent/.git'
-Peff
Jeff King· Apr 22, 2008, 20:05 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Tue, Apr 22, 2008 at 09:52:46AM -0700, Junio C Hamano wrote:
Show 13 quoted lines
> >   2. In my usage, pushing a branch to a tag (or vice versa) is the
> >      exception, so I don't mind favoring pushing like types to like
> >      types.
> >
> > But I recognize that (2) is based on my own workflow, so if people
> > disagree, I guess it isn't so for everyone.
> 
> So the proposal is:
> 
> 	"git push $there $commit:$name", when $name does not begin with
> 	refs/, is interpreted as "git push $there $commit:refs/heads/$name"
> 
> right?  I think that makes sense, at least to me.
No, the proposal is:
        "git push $there $commit:$name", when $name does not begin with
        refs/, is interpreted as "git push $there
        $commit:$prefix/$name", where $prefix is determined by resolving
        $commit and pulling off its first two directories.

(or maybe this should just be picky and DWIM only for refs/heads and refs/tags). So "git push v1.0" is the same as "git push v1.0:v1.0", which is the same as "git push refs/tags/v1.0:refs/tags/v1.0".

-Peff
Junio C Hamano· Apr 22, 2008, 20:45 UTC · re: Jeff King · lore

Re: Friendly refspecs

Jeff King <peff@peff.net> writes:
Show 10 quoted lines
> No, the proposal is:
>
>         "git push $there $commit:$name", when $name does not begin with
>         refs/, is interpreted as "git push $there
>         $commit:$prefix/$name", where $prefix is determined by resolving
>         $commit and pulling off its first two directories.
>
> (or maybe this should just be picky and DWIM only for refs/heads and
> refs/tags). So "git push v1.0" is the same as "git push v1.0:v1.0",
> which is the same as "git push refs/tags/v1.0:refs/tags/v1.0".
Where is $there in your example?

Funny but I recall recently running "git push ko v1.5.5.1" and it all worked as expected...

I thought the original poster's example was
	git push $there $commit:branch2
where $commit happened to be "branch1".  Would we dwim
	git push $there branch1~4:this_is_known_ok
to refs/heads/?
Jeff King· Apr 22, 2008, 21:52 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Tue, Apr 22, 2008 at 01:45:05PM -0700, Junio C Hamano wrote:
Show 10 quoted lines
> >         "git push $there $commit:$name", when $name does not begin with
> >         refs/, is interpreted as "git push $there
> >         $commit:$prefix/$name", where $prefix is determined by resolving
> >         $commit and pulling off its first two directories.
> >
> > (or maybe this should just be picky and DWIM only for refs/heads and
> > refs/tags). So "git push v1.0" is the same as "git push v1.0:v1.0",
> > which is the same as "git push refs/tags/v1.0:refs/tags/v1.0".
> 
> Where is $there in your example?
Heh, sorry. s/git push/& $there/g.
> Funny but I recall recently running "git push ko v1.5.5.1" and it all
> worked as expected...

I'm not sure what you mean here. Yes, we already special case "git push $there $ref" into "git push $there $ref:$ref", except we use the fully-qualified ref name for the right-hand side. I mention it because I think of this as simply extending that dwimmery to $commit:branch2. That is, there is a complete and unambiguous refspec like "refs/heads/branch1:refs/heads/branch2", and the others are logical DWIM shorthands that expand into such a refspec.

Show 9 quoted lines
> I thought the original poster's example was
> 
> 	git push $there $commit:branch2
> 
> where $commit happened to be "branch1".  Would we dwim
> 
> 	git push $there branch1~4:this_is_known_ok
> 
> to refs/heads/?

I'm not sure what you mean by "this_is_known_ok". Do you mean the remote already has such a ref? I think the dwim is:

  1. if the destination ref is fully qualified, use that
  2. if the destination ref is not fully qualified, but resolves
     unambiguously to a ref on the remote, use that
  3. otherwise, do the dwim we are talking about, which is to qualify it
     using the same type as the source ref

So if you meant "the remote has such a ref", then no, I think we stick with the current behavior (2).

But I think what you were getting at is: "what is the source type of branch~4"? I am inclined to say "the same as the source type of branch", but I can see how one might think that is getting a little crazy. Related is the question of "what is the source type of <sha1>". In that case, we should almost certainly give an error as we do now. Putting "branch~4" into that category (or HEAD if it is detached) makes some sense to me.

-Peff
Teemu Likonen· Apr 23, 2008, 04:24 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

Junio C Hamano wrote (2008-04-22 13:45 -0700):
Show 9 quoted lines
> I thought the original poster's example was
> 
> 	git push $there $commit:branch2
> 
> where $commit happened to be "branch1".  Would we dwim
> 
> 	git push $there branch1~4:this_is_known_ok
> 
> to refs/heads/?

I guess this is what I meant. My original question was about inconsistent user interface: "git push $there branch1" creates branch1 on the remote side (if it does not exist) but "git push $there branch1:branch2" gives an error if branch2 does not exist (branch1:refs/heads/branch2 is required).

The case has become much more complicated since, so I just speak aloud my hope that need for refs/ paths in common situations would be reduced to minimum.

Junio C Hamano· Apr 23, 2008, 05:52 UTC · re: Teemu Likonen · lore

Re: Friendly refspecs

Teemu Likonen <tlikonen@iki.fi> writes:
Show 21 quoted lines
> Junio C Hamano wrote (2008-04-22 13:45 -0700):
>
>> I thought the original poster's example was
>> 
>> 	git push $there $commit:branch2
>> 
>> where $commit happened to be "branch1".  Would we dwim
>> 
>> 	git push $there branch1~4:this_is_known_ok
>> 
>> to refs/heads/?
>
> I guess this is what I meant. My original question was about
> inconsistent user interface: "git push $there branch1" creates branch1
> on the remote side (if it does not exist) but "git push $there
> branch1:branch2" gives an error if branch2 does not exist
> (branch1:refs/heads/branch2 is required).
>
> The case has become much more complicated since, so I just speak aloud
> my hope that need for refs/ paths in common situations would be reduced
> to minimum.

I think everybody involved in this discussion understands _that_. The issue is that you would not have said "branch2" in real life, but used some word that is _not_ "branch" to name the thing, and there is no way for git to guess correctly if you meant to create a branch or a light-weight tag.

There is no inconsistency. "push $branch1" has a special case logic to favor "the same name". You invoked "src:dst" syntax that is general purpose which does not dwim.

Historically we did not favor one way or another for the general purpose syntax. I think Jeff's proposed heuristics to favor branch if a branch tip is pushed and tag if a tag is pushed makes sense.

Andreas Ericsson· Apr 23, 2008, 06:24 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

Junio C Hamano wrote:
Show 29 quoted lines
> Teemu Likonen <tlikonen@iki.fi> writes:
> 
>> Junio C Hamano wrote (2008-04-22 13:45 -0700):
>>
>>> I thought the original poster's example was
>>>
>>> 	git push $there $commit:branch2
>>>
>>> where $commit happened to be "branch1".  Would we dwim
>>>
>>> 	git push $there branch1~4:this_is_known_ok
>>>
>>> to refs/heads/?
>> I guess this is what I meant. My original question was about
>> inconsistent user interface: "git push $there branch1" creates branch1
>> on the remote side (if it does not exist) but "git push $there
>> branch1:branch2" gives an error if branch2 does not exist
>> (branch1:refs/heads/branch2 is required).
>>
>> The case has become much more complicated since, so I just speak aloud
>> my hope that need for refs/ paths in common situations would be reduced
>> to minimum.
> 
> I think everybody involved in this discussion understands _that_.  The
> issue is that you would not have said "branch2" in real life, but used
> some word that is _not_ "branch" to name the thing, and there is no way
> for git to guess correctly if you meant to create a branch or a
> light-weight tag.
> 

If the src ref is not a commit sha1, the user will almost certainly want to create the same *type* of ref on the remote side, so

git tag foo git branch boo git push $there foo:wip git push $there boo:wip-2008-04-24

would, on the remote side, create the branch "wip" and the tag "wip-2008-04-24"

I for one would certainly like that, and I don't think very many will be surprised at that behaviour.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231
Jeff King· Apr 23, 2008, 09:16 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

On Tue, Apr 22, 2008 at 10:52:06PM -0700, Junio C Hamano wrote:
> Historically we did not favor one way or another for the general purpose
> syntax.  I think Jeff's proposed heuristics to favor branch if a branch
> tip is pushed and tag if a tag is pushed makes sense.
OK, here is a cleaned up patch with tests.

-- >8 -- push: allow unqualified dest refspecs to DWIM

Previously, a push like:
  git push remote src:dst
would go through the following steps:
  1. check for an unambiguous 'dst' on the remote; if it
     exists, then push to that ref
  2. otherwise, check if 'dst' begins with 'refs/'; if it
     does, create a new ref
  3. otherwise, complain because we don't know where in the
     refs hierarchy to put 'dst'

However, in some cases, we can guess about the ref type of 'dst' based on the ref type of 'src'. Specifically, before complaining we now check:

  2.5. if 'src' resolves to a ref starting with refs/heads
       or refs/tags, then prepend that to 'dst'

So now this creates a new branch on the remote, whereas it previously failed with an error message:

  git push master:newbranch

Note that, by design, we limit this DWIM behavior only to source refs which resolve exactly (including symrefs which resolve to existing refs). We still complain on a partial destination refspec if the source is a raw sha1, or a ref expression such as 'master~10'.

Signed-off-by: Jeff King <peff@peff.net>
---
 remote.c              |   32 +++++++++++++++++++++++++++++---
 t/t5516-fetch-push.sh |   40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/remote.c b/remote.c
index 06ad156..2d9af40 100644
--- a/remote.c
+++ b/remote.c
@@ -812,6 +812,26 @@ static struct ref *make_linked_ref(const char *name, struct ref ***tail)
 	return ret;
 }
 
+static char *guess_ref(const char *name, struct ref *peer)
+{
+	struct strbuf buf = STRBUF_INIT;
+	unsigned char sha1[20];
+
+	const char *r = resolve_ref(peer->name, sha1, 1, NULL);
+	if (!r)
+		return NULL;
+
+	if (!prefixcmp(r, "refs/heads/"))
+		strbuf_addstr(&buf, "refs/heads/");
+	else if (!prefixcmp(r, "refs/tags/"))
+		strbuf_addstr(&buf, "refs/tags/");
+	else
+		return NULL;
+
+	strbuf_addstr(&buf, name);
+	return strbuf_detach(&buf, NULL);
+}
+
 static int match_explicit(struct ref *src, struct ref *dst,
 			  struct ref ***dst_tail,
 			  struct refspec *rs,
@@ -820,6 +840,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
 	struct ref *matched_src, *matched_dst;
 
 	const char *dst_value = rs->dst;
+	char *dst_guess;
 
 	if (rs->pattern)
 		return errs;
@@ -866,10 +887,15 @@ static int match_explicit(struct ref *src, struct ref *dst,
 	case 0:
 		if (!memcmp(dst_value, "refs/", 5))
 			matched_dst = make_linked_ref(dst_value, dst_tail);
+		else if((dst_guess = guess_ref(dst_value, matched_src)))
+			matched_dst = make_linked_ref(dst_guess, dst_tail);
 		else
-			error("dst refspec %s does not match any "
-			      "existing ref on the remote and does "
-			      "not start with refs/.", dst_value);
+			error("unable to push to unqualified destination: %s\n"
+			      "The destination refspec neither matches an "
+			      "existing ref on the remote nor\n"
+			      "begins with refs/, and we are unable to "
+			      "guess a prefix based on the source ref.",
+			      dst_value);
 		break;
 	default:
 		matched_dst = NULL;
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index f93a100..0a757d5 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -273,6 +273,37 @@ test_expect_success 'push with colon-less refspec (4)' '
 
 '
 
+test_expect_success 'push head with non-existant, incomplete dest' '
+
+	mk_test &&
+	git push testrepo master:branch &&
+	check_push_result $the_commit heads/branch
+
+'
+
+test_expect_success 'push tag with non-existant, incomplete dest' '
+
+	mk_test &&
+	git tag -f v1.0 &&
+	git push testrepo v1.0:tag &&
+	check_push_result $the_commit tags/tag
+
+'
+
+test_expect_success 'push sha1 with non-existant, incomplete dest' '
+
+	mk_test &&
+	test_must_fail git push testrepo `git rev-parse master`:foo
+
+'
+
+test_expect_success 'push ref expression with non-existant, incomplete dest' '
+
+	mk_test &&
+	test_must_fail git push testrepo master^:branch
+
+'
+
 test_expect_success 'push with HEAD' '
 
 	mk_test heads/master &&
@@ -311,6 +342,15 @@ test_expect_success 'push with +HEAD' '
 
 '
 
+test_expect_success 'push HEAD with non-existant, incomplete dest' '
+
+	mk_test &&
+	git checkout master &&
+	git push testrepo HEAD:branch &&
+	check_push_result $the_commit heads/branch
+
+'
+
 test_expect_success 'push with config remote.*.push = HEAD' '
 
 	mk_test heads/local &&
-- 
1.5.5.1.69.g9c889.dirty
Jeff King· Apr 23, 2008, 09:21 UTC · re: Jeff King · lore

Re: Friendly refspecs

On Wed, Apr 23, 2008 at 05:16:06AM -0400, Jeff King wrote:
Show 5 quoted lines
> > Historically we did not favor one way or another for the general purpose
> > syntax.  I think Jeff's proposed heuristics to favor branch if a branch
> > tip is pushed and tag if a tag is pushed makes sense.
> 
> OK, here is a cleaned up patch with tests.

Oops, I forgot to mention: there is a broken test in t5516 that is revealed by this change. The patch below should be applied before the DWIM one.

-- >8 -- t5516: remove ambiguity test (1)

This test tried to push into a remote with ambiguous refs in remotes/$x/master and remotes/$y/master. However, the remote never actually tells us about the refs/remotes hierarchy, so we don't even see this ambiguity.

The test happened to pass because we were simply looking for failure, and the test fails for another reason: the dst refspec does not exist and does not begin with refs/, making it invalid.

Signed-off-by: Jeff King <peff@peff.net>
---
 t/t5516-fetch-push.sh |   14 +-------------
 1 files changed, 1 insertions(+), 13 deletions(-)
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 6d7e738..f93a100 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -209,19 +209,7 @@ test_expect_success 'push with weak ambiguity (2)' '
 
 '
 
-test_expect_success 'push with ambiguity (1)' '
-
-	mk_test remotes/origin/master remotes/frotz/master &&
-	if git push testrepo master:master
-	then
-		echo "Oops, should have failed"
-		false
-	else
-		check_push_result $the_first_commit remotes/origin/master remotes/frotz/master
-	fi
-'
-
-test_expect_success 'push with ambiguity (2)' '
+test_expect_success 'push with ambiguity' '
 
 	mk_test heads/frotz tags/frotz &&
 	if git push testrepo master:frotz
-- 
1.5.5.1.69.g9c889.dirty
Teemu Likonen· Apr 23, 2008, 11:15 UTC · re: Jeff King · lore

Re: Friendly refspecs

Jeff King wrote (2008-04-23 05:21 -0400):
Show 12 quoted lines
> On Wed, Apr 23, 2008 at 05:16:06AM -0400, Jeff King wrote:
> 
> > > Historically we did not favor one way or another for the general
> > > purpose syntax.  I think Jeff's proposed heuristics to favor
> > > branch if a branch tip is pushed and tag if a tag is pushed makes
> > > sense.
> > 
> > OK, here is a cleaned up patch with tests.
> 
> Oops, I forgot to mention: there is a broken test in t5516 that is
> revealed by this change. The patch below should be applied before the
> DWIM one.

I did some testing and your patches seem to work. I think push refspecs are frendlier now. :) It's great to see you guys taking users seriously and working on possible problems. Thanks!

Junio C Hamano· Apr 9, 2008, 21:21 UTC · re: Teemu Likonen · lore

Re: Friendly refspecs

Teemu Likonen <tlikonen@iki.fi> writes:

[By the way, please never redirect the response to your messages away from you with:

    Mail-Followup-To: Jeff King <peff@peff.net>, Ingo Molnar <mingo@elte.hu>,
            git@vger.kernel.org

You wasted 30 seconds of my (and anybody who potentially wanted to give advice to you) time by forcing me fix the To: header while composing this response. I know Jeff understands what I am going to mention, and I do not want to waste his time by putting him on To: header.]

> Currently "git fetch <URL>" does not seem to do anything useful for
> non-git-hackers. It seems to fetch objects but not create any branches
> referring to them.
I'd suggest you to study:
  http://thread.gmane.org/gmane.comp.version-control.git/31351/focus=31634
Not everybody wants remote tracking.
Teemu Likonen· Apr 10, 2008, 07:38 UTC · re: Junio C Hamano · lore

Re: Friendly refspecs

Junio C Hamano wrote (2008-04-09 14:21 -0700):
Show 5 quoted lines
> [By the way, please never redirect the response to your messages away from
> you with:
> 
>     Mail-Followup-To: Jeff King <peff@peff.net>, Ingo Molnar <mingo@elte.hu>,
>             git@vger.kernel.org

Sorry, didn't even know such header existed. After consulting Mutt's manual and some googling I think I understand it now. I'm a subscriber to git list (and my Mutt knows that) and Mail-Followup-To told everyone's MUAs to not include me in recipient list since I get everything through the list. But this is configurable and generating Mail-Followup-To should be now turned off.

Show 9 quoted lines
> > Currently "git fetch <URL>" does not seem to do anything useful for
> > non-git-hackers. It seems to fetch objects but not create any
> > branches referring to them.
> 
> I'd suggest you to study:
> 
>   http://thread.gmane.org/gmane.comp.version-control.git/31351/focus=31634
> 
> Not everybody wants remote tracking.
Thanks, and I agree. Me neither always want remote tracking. Git's
current behaviour to only create/update FETCH_HEAD seems actually better
- now that I know what it does. I think it's a good idea to show "[new
branch] foo -> FETCH_HEAD" after fetching.
Santiago Gala· Apr 12, 2008, 18:59 UTC · re: Jeff King · lore

Re: git annoyances

Jeff King <peff <at> peff.net> writes:
(...)
Show 5 quoted lines
> Unless you are planning on merging this remote a lot, the common usage
> is probably to just forget the remote stuff and do:
> 
>   git pull ~/linux-2.6-x86.git latest
> 

Well, he wants to *merge*, not really to *pull*. A problem I'm encountering a lot with git is this kind of mismatch between the naming of the command and the actions. Most of the time the things make sense when they are explained, but they are not intuitive and I forget them once and again.

I have special problems with "pull" and "fetch". I mean, for me "pull" is about "pulling code" from other repo, but not really to the working copy, or at least not always to the working copy.

In fact, the first line of git-pull --help is "Fetch from and merge with another repository or a local" (pulling together the other two words, fetch and merge, if you allow the pun). For my very limited git intuition, and I guess for a lot of people too, pull is just "fetch".

Daniel Barkalow· Apr 9, 2008, 19:21 UTC · re: Ingo Molnar · lore

Re: git annoyances

On Wed, 9 Apr 2008, Ingo Molnar wrote:
Show 24 quoted lines
> 
> i just had a rather annoying session with git - here's the dump and 
> commentary, in case anyone is interested in usability fineprint.
> 
> it was with git-core-1.5.4.3-2.fc8 - so if it's all fixed/improved in 
> 1.5.5, or if this is blatant user error for which i deserve to be 
> punished then my apologies!
> 
> usually i just have a single git repo that tracks everything 
> interesting, but this time i did something i rarely do: i tried to merge 
> one local tree of mine into another local tree of mine. So i had no 
> commands (or even concepts) cached in my short-term memory that would 
> achieve this goal, i just tried the commands that i thought to be 
> 'obvious', without applying much (or any) IQ to those commands:
> 
>  $ cd linux-2.6-sched-devel.git
> 
>  $ git-remote add ~/linux-2.6-x86.git
> 
>  $ git-remote show x86
>   * remote x86
>     URL: /home/mingo/linux-2.6-x86.git
>   New remote branches (next fetch will store in remotes/x86)
>   base for-akpm for-linus latest master testing
Good so far.
>  $ git-merge x86/latest
>  x86/latest - not something we can merge

Git is missing the fact that, while refs/remotes/x86/latest doesn't exist, there is a fetch rule that would create it. It should suggest "git fetch x86" or "git fetch x86 latest". This is a bit tricky, because you've used a shorthand for something that doesn't exist, so there isn't a unique answer for which full name you're looking for, but there is a unique solution (in this case) for which one could be created by a pattern you have.

Show 9 quoted lines
>  #
>  # ho hum. Not something 'we' can merge. Do i care? :-) There's no 
>  # actionable reference given to the user about how to resolve this 
>  # problem. So i kept on trying:
>  #
> 
>  $ git-fetch x86/latest
>  fatal: 'x86/latest': unable to chdir or not a git archive
>  fatal: The remote end hung up unexpectedly
The right error message here would probably be:
/home/mingo/linux-2.6-sched-devel.git/x86/latest: No such file or directory

That should at least tell you what git thinks, incorrectly, that you want it to do, and why it doesn't work.

Show 44 quoted lines
> what got me going after experimenting around some more was this exact 
> command:
> 
>  $ git-pull x86 latest
> 
> (that fetch+merge went problem-free.)
> 
> but it was a PITA and all of git's messages about the problem were not 
> only unhelpful, they confused me into looking for problems where there 
> were none IMO. I was starting to wonder whether i have to have some git 
> daemon running on that box for example. But in retrospect IMO it was 
> rather clear from the outset what i wanted git to do (merge the tip of 
> my other tree into the tip of this tree, on the local box, no frills), i 
> just didnt figure out the exact command to do it.
> 
> another (minor) usability annoyance: one of the first things i tried was 
> to verify the remote setup, via:
> 
> $ git-remote show
> 
> which gave me this answer:
> 
>  Usage: git remote show <remote>
> 
> then i tried git-remote show -a (to list all repositories, etc.) - what 
> i didnt figure out was to show all repositories is to do a simple 
> "git-remote". I think "git-remote show" should output all repositories, 
> or at least indicate it in its help line what to do to get such a list. 
> (for us poor sobs forgetting commandline details ;)
> 
> also, the first natural thing i did was to just type:
> 
>  $ git-merge ~/linux-2.6-x86.git/
> 
> which i naively assumed would sort things out for me and provide some 
> reasonable default behavior - but instead it just gave an annoyingly 
> unhelpful error message:
> 
>  /home/mingo/linux-2.6-x86.git/ - not something we can merge
> 
> there should really be a consciously established "route of failure 
> resolution" - directing people towards relevant sources of information 
> or commands when the git command-line utilities return some error due to 
> user incompetence. Otherwise users just guess around and get frustrated.

I'm not sure we can figure out what the user actually meant in this case; there's just too much overlap in namespaces to determine reliably that you were giving it a remote repository on the local filesystem rather than anything else.

	-Daniel
*This .sig left intentionally blank*
Ingo Molnar· Apr 9, 2008, 20:41 UTC · re: Daniel Barkalow · lore

Re: git annoyances

* Daniel Barkalow <barkalow@iabervon.org> wrote:
Show 20 quoted lines
> > also, the first natural thing i did was to just type:
> > 
> >  $ git-merge ~/linux-2.6-x86.git/
> > 
> > which i naively assumed would sort things out for me and provide 
> > some reasonable default behavior - but instead it just gave an 
> > annoyingly unhelpful error message:
> > 
> >  /home/mingo/linux-2.6-x86.git/ - not something we can merge
> > 
> > there should really be a consciously established "route of failure 
> > resolution" - directing people towards relevant sources of 
> > information or commands when the git command-line utilities return 
> > some error due to user incompetence. Otherwise users just guess 
> > around and get frustrated.
> 
> I'm not sure we can figure out what the user actually meant in this 
> case; there's just too much overlap in namespaces to determine 
> reliably that you were giving it a remote repository on the local 
> filesystem rather than anything else.

well, current git got to /home/mingo/linux-2.6-x86.git/ which is a local path. (it is printing it in the error message above) So i think it was rather unambiguous what i meant and Git knew about it, right?

but even if it _was_ ambiguous, i think tools should generally default to a minimal amount of hassle for new users and should try to pick reasonable "action" versus any "inaction". (as long as the behavior is still deterministic and reasonable even to the long-time user)

but more importantly, i think this whole problem area has to be handled with a slightly different kind of mindset than other, more technical aspects of Git.

Humans, and in particular males, when they see or learn new things, are very emotion-driven. The first 1-2 minutes (often just the first few seconds) have a very strong influence on whether that person 'likes' a new topic, tool or gizmo he is checking out - or not. Males often think of themselves as being objective when shopping new items - while in reality more than 90% of their purchasing decisions are emotion-driven and it's all set and done in the first 10 seconds of visual contact. (this ration is far higher than for females)

Command-line tools like Git are at heavy natural disadvantage compared to say GUI tools because the "first impression" is so minimalistic and relatively unremarkable. A GUI can get people hooked by making the first 10% look easy just via old-fashioned, dishonest visual deception.

so basically for 90% of the new users, we've got 2-3 shots or we lose their "sympathy". Starting with an error message is bad. Being uninformative about what happened is bad. Making the user wait without signalling why he is waiting is bad. Etc. etc. I think this experience of mine was a reasonable simulation of a first-time user reaction (by virtue of me having forgotten certain Git details).

And the moment a negative first-time impression has settled in it's very hard to overcome that emotional mindset and barrier. People might still think "Git is quirky" even if we do all things perfectly from that point on. The same holds for the other direction: a positive first-time impression is harder to destroy, even if it turns out to be not that simple later on.

A tool's reaction back to first-time users is like a decision tree: every negative reaction, every error message, every unreasonable wait, every uninformative output is a way for the user to exit our ecosystem and to never discover the true strengths of Git.

So i really think that maintaining this aspect of Git and in essence Huffman-optimizing the interface and the learning curve for first-time Git users is perhaps the most important thing. Especially since some users like me will often re-learn Git details that they use rarely.

Getting these details right is _extremely hard_, because the people who are capable of fixing these details have long forgotten the first-time annoyances they had! (if they had any - often developers are statistically lucky and never hit any pitfalls.)

It's doubly hard because Git developers work on Git exactly because they _like_ it, so one's own positive experience has to be contrasted to the prospect of negative first-time experience.

It's triple hard because it might also mean changing some things that have been done in Git since the start of the project. A negative experience that isnt some technical problem in the strict sense - it's an emotional thing that is much harder to define and much harder to agree on and improve.

So i think it's really hard mentally - and i'm positively surprised by the many constructive and positive reactions that my mail generated.

Improving this area is perhaps even harder than adding new functionality 
- but i think it's a key and extremely strategic aspect of Git, because 
it affects the very heart of the Git project: it maximizes the influx of 
new users (who also include future Git developers btw.) and minimizes 
outflux of existing users.
	Ingo
Daniel Barkalow· Apr 10, 2008, 14:08 UTC · re: Ingo Molnar · lore

Re: git annoyances

On Wed, 9 Apr 2008, Ingo Molnar wrote:
Show 27 quoted lines
> 
> * Daniel Barkalow <barkalow@iabervon.org> wrote:
> 
> > > also, the first natural thing i did was to just type:
> > > 
> > >  $ git-merge ~/linux-2.6-x86.git/
> > > 
> > > which i naively assumed would sort things out for me and provide 
> > > some reasonable default behavior - but instead it just gave an 
> > > annoyingly unhelpful error message:
> > > 
> > >  /home/mingo/linux-2.6-x86.git/ - not something we can merge
> > > 
> > > there should really be a consciously established "route of failure 
> > > resolution" - directing people towards relevant sources of 
> > > information or commands when the git command-line utilities return 
> > > some error due to user incompetence. Otherwise users just guess 
> > > around and get frustrated.
> > 
> > I'm not sure we can figure out what the user actually meant in this 
> > case; there's just too much overlap in namespaces to determine 
> > reliably that you were giving it a remote repository on the local 
> > filesystem rather than anything else.
> 
> well, current git got to /home/mingo/linux-2.6-x86.git/ which is a local 
> path. (it is printing it in the error message above) So i think it was 
> rather unambiguous what i meant and Git knew about it, right?

Actually, your shell did that. I don't think git can tell that the user typed something different and the shell converted it because it's a local path.

> but even if it _was_ ambiguous, i think tools should generally default 
> to a minimal amount of hassle for new users and should try to pick 
> reasonable "action" versus any "inaction". (as long as the behavior is 
> still deterministic and reasonable even to the long-time user)

It's hard to evaluate proposals for extending cases from inaction to some action because in trying to keep it deterministic, you have to decide whether future, possibly more compelling, extensions might want to overlap the space of commands. It's more conservative to have the command suggest some things the user might have meant, even if that's sometimes a list of one, so that the user doesn't come to rely on behavior that is only deterministic within a vaguely-delineated area.

Show 24 quoted lines
> but more importantly, i think this whole problem area has to be handled 
> with a slightly different kind of mindset than other, more technical 
> aspects of Git.
> 
> Humans, and in particular males, when they see or learn new things, are 
> very emotion-driven. The first 1-2 minutes (often just the first few 
> seconds) have a very strong influence on whether that person 'likes' a 
> new topic, tool or gizmo he is checking out - or not. Males often think 
> of themselves as being objective when shopping new items - while in 
> reality more than 90% of their purchasing decisions are emotion-driven 
> and it's all set and done in the first 10 seconds of visual contact. 
> (this ration is far higher than for females)
> 
> Command-line tools like Git are at heavy natural disadvantage compared 
> to say GUI tools because the "first impression" is so minimalistic and 
> relatively unremarkable. A GUI can get people hooked by making the first 
> 10% look easy just via old-fashioned, dishonest visual deception.
> 
> so basically for 90% of the new users, we've got 2-3 shots or we lose 
> their "sympathy". Starting with an error message is bad. Being 
> uninformative about what happened is bad. Making the user wait without 
> signalling why he is waiting is bad. Etc. etc. I think this experience 
> of mine was a reasonable simulation of a first-time user reaction (by 
> virtue of me having forgotten certain Git details).

I think that it's far enough along before a user types "git merge ..." that we've got a chance to give a suggestive error message instead of just doing something, particularly if the thing we might do might be wrong and either annoying to clean up or slow. (OTOH, "git clone ..." had better work, and I think it does)

And I agree strongly with the need for the error messages in the cases where the user was closer to be clear and suggest the right thing.

> So i really think that maintaining this aspect of Git and in essence 
> Huffman-optimizing the interface and the learning curve for first-time 
> Git users is perhaps the most important thing. Especially since some 
> users like me will often re-learn Git details that they use rarely.

On the other hand, there's a conflict between having git do what the user seems to want it to do and having git's commands delineated by concepts that users need to know, such that users will be assisted in learning those concepts (and therefore have an easier time getting the results they expect from git consistantly). For example, "merge" works on information you have within the repository, and "fetch" brings information into the repository. In some cases, we could guess that the user has typed "merge" but wants to bring information into the repository, but we won't always be right, and we want the user to learn how to tell git unambiguous things.

Show 23 quoted lines
> Getting these details right is _extremely hard_, because the people who 
> are capable of fixing these details have long forgotten the first-time 
> annoyances they had! (if they had any - often developers are 
> statistically lucky and never hit any pitfalls.)
> 
> It's doubly hard because Git developers work on Git exactly because they 
> _like_ it, so one's own positive experience has to be contrasted to the 
> prospect of negative first-time experience.
> 
> It's triple hard because it might also mean changing some things that 
> have been done in Git since the start of the project. A negative 
> experience that isnt some technical problem in the strict sense - it's 
> an emotional thing that is much harder to define and much harder to 
> agree on and improve.
> 
> So i think it's really hard mentally - and i'm positively surprised by 
> the many constructive and positive reactions that my mail generated.
> 
> Improving this area is perhaps even harder than adding new functionality 
> - but i think it's a key and extremely strategic aspect of Git, because 
> it affects the very heart of the Git project: it maximizes the influx of 
> new users (who also include future Git developers btw.) and minimizes 
> outflux of existing users.

I think the market segment that most git developers would really like to get is the projects that they work on aside from git. There's a substantial itch to make git sufficiently compelling that nobody would make them use CVS/SVN/Perforce/ClearCase/etc. This has a significant usability-to-new-users component, and so there's more attention to that than in projects where use of the project doesn't require getting particular other people to use it.

	-Daniel
*This .sig left intentionally blank*
Junio C Hamano· Apr 9, 2008, 21:04 UTC · re: Ingo Molnar · lore

Re: git annoyances

Ingo Molnar <mingo@elte.hu> writes:
> i just had a rather annoying session with git - here's the dump and 
> commentary, in case anyone is interested in usability fineprint.

Thanks. It is always enlightening to see this kind of walkthru session to learn where the UI warts are. The ones with concrete suggestions for improvements are even more appreciated.

Show 10 quoted lines
> usually i just have a single git repo that tracks everything 
> interesting, but this time i did something i rarely do: i tried to merge 
> one local tree of mine into another local tree of mine. So i had no 
> commands (or even concepts) cached in my short-term memory that would 
> achieve this goal, i just tried the commands that i thought to be 
> 'obvious', without applying much (or any) IQ to those commands:
>
>  $ cd linux-2.6-sched-devel.git
>
>  $ git-remote add ~/linux-2.6-x86.git

You told git that "I'll interact with this other repository from now on, so please help me with some extra settings to do so. Namely I do not want to keep typing it in full URL all the time so I want an abbreviated way to tell you I am talking about this remote repository, and also I want to have set of remote tracking branches for this one".

Maybe "remote add" is not quite the right name to convey the above concept.

Show 5 quoted lines
>  $ git-remote show x86
>   * remote x86
>     URL: /home/mingo/linux-2.6-x86.git
>   New remote branches (next fetch will store in remotes/x86)
>   base for-akpm for-linus latest master testing
So the command did as you told it to.
>  $ git-merge x86/latest
>  x86/latest - not something we can merge

You told git "I want to merge a commit into the current branch, and that commit is called x86/latest". Alas, no such commit exists in your repository (yet). Should we be saying "no such commit exists, you need to fetch it from elsewhere first"?

>  $ git-fetch x86/latest
>  fatal: 'x86/latest': unable to chdir or not a git archive
>  fatal: The remote end hung up unexpectedly

"Not a git archive" should be clear enough. You already said "remote show x86" correctly above, and it makes me wonder why you are now saying "x86/latest", not "x86" without "latest".

In other words, "git fetch x86".

With that, you would tell git "Hey, I've already told you what I want you to do with this short-hand name "x86". It is the name for the long URL I've previously given you and I want you to fetch from that repository, and I want its branches to be stored in remote tracking branches in my repository".

But you didn't. You are not taking advantage of your previous "git remote add".

I am suspecting that a cause of this confusion is partly because earlier in 1.3.0 days we tried to make things easy for CVS migrants where they always interact with a single "upstream" repository and with _the_ single branch, and we were _too_ successful in doing so.

That made us allowing the users to type "git pull" and "git fetch" without parameters. This is generally a good thing: shorter to type for doing common things is always good, as long as the user knows what he is doing.

But at the same time, this allowed docs and cheat-sheets that mention only the form without parameters and not the normative "repository refspec" form. This dumbed down the users not understand that in that context fetch (and pull, which is a fetch followed by a merge) is always happening against a single branch of single remote repository, the way to name remote repository and its branch(es) is to give them as separate parameters, and their not typing the pair explicitly is a mere convenience feature. This particular aspect of the shorthand is actually very bad. It makes the mental model fuzzy, and hiding important rules of how the world works from new people would lead them to unnecessary confusion. In short, we made it harder for the new people to "get" it.

The introductory documents may need to be updated to teach explicit "git pull $repo $branch" form first, and if they are short documents, end in introductory phase and leave the remainder to "further reading", they should probably be fixed not talk about the shorthand form "git pull $nick" and "git pull" without parameters at all. That may help fixing this mental-model breakdown.

>  $ git-pull x86 latest
>
> (that fetch+merge went problem-free.)
Yes.

Because git is distributed, a branch in the global scope is named with a pair "remote" and "branch" as two separate parameters, and we consistently do so. Always. Just like you are supposed to say in your "Linus, please pull" requests (e.g. http://article.gmane.org/gmane.linux.kernel/321590).

> but it was a PITA and all of git's messages about the problem were not 
> only unhelpful, they confused me into looking for problems where there 
> were none IMO.

Yes, we need to teach "git" to do more mind-reading (I am not being sarcastic). There should be a pattern in common user errors that share their roots to the same user misperception, and if we can identify that, maybe we can make git guess what the user was really trying to do and give better error messages than it currently does.

Show 9 quoted lines
> also, the first natural thing i did was to just type:
>
>  $ git-merge ~/linux-2.6-x86.git/
>
> which i naively assumed would sort things out for me and provide some 
> reasonable default behavior - but instead it just gave an annoyingly 
> unhelpful error message:
>
>  /home/mingo/linux-2.6-x86.git/ - not something we can merge
I'd agree that it is fair to get frustrated with this.

We actually did not have "git merge" as the first level UI citizen for quite some time, and the way to merge in _anything_ was done with "git pull", even within the local repository. If you did not know "git merge" existed, the above would have been either one of

	$ git pull ~/linux-2.6-x86.git/
	$ git pull ~/linux-2.6-x86.git/ master

and would have been nicer. But people wanted "git merge" which is a purely local operation, which made (and still does makes) sense. But now people need to know two different commands, one that works globally and the other that works locally.

C.f.
 http://thread.gmane.org/gmane.comp.version-control.git/10778/focus=10900
 http://thread.gmane.org/gmane.comp.version-control.git/31351/focus=31528
 http://thread.gmane.org/gmane.comp.version-control.git/31351/focus=31490
> there should really be a consciously established "route of failure 
> resolution" - directing people towards relevant sources of information 
> or commands when the git command-line utilities return some error due to 
> user incompetence. Otherwise users just guess around and get frustrated.

Yes, I called it mind-reading above, but we are wishing for the same thing.

by the way, because you already paid for your Shift keys, you might want to use it consistently to enhance readability. i find it somewhat irritating not to be able to tell where each sentence begins with enough visual cues (i.e. full-stop, two spaces and initial capital letter) and first person subject not spelled with capital letter i.

Jon Loeliger· Apr 9, 2008, 21:39 UTC · re: Junio C Hamano · lore

Re: git annoyances

Junio C Hamano wrote:
>
> The introductory documents may need to be updated to teach explicit "git
> pull $repo $branch" form first,
Hey Junio,
I'm hearing you here! :-)

I think a furtherance of this notion is to teach "git fetch ; git merge" before "git pull".

Thanks, jdl

Nicolas Pitre· Apr 9, 2008, 23:45 UTC · re: Jon Loeliger · lore

Re: git annoyances

On Wed, 9 Apr 2008, Jon Loeliger wrote:
Show 12 quoted lines
> Junio C Hamano wrote:
> > 
> 
> > The introductory documents may need to be updated to teach explicit "git
> > pull $repo $branch" form first,
> 
> Hey Junio,
> 
> I'm hearing you here! :-)
> 
> I think a furtherance of this notion is to
> teach "git fetch ; git merge" before "git pull".
Amen!
Nicolas
Jeff King· Apr 9, 2008, 21:45 UTC · re: Junio C Hamano · lore

Re: git annoyances

On Wed, Apr 09, 2008 at 02:04:33PM -0700, Junio C Hamano wrote:
Show 6 quoted lines
> The introductory documents may need to be updated to teach explicit "git
> pull $repo $branch" form first, and if they are short documents, end in
> introductory phase and leave the remainder to "further reading", they
> should probably be fixed not talk about the shorthand form "git pull
> $nick" and "git pull" without parameters at all.  That may help fixing
> this mental-model breakdown.

For me personally, I think this bottom-up approach makes the most sense to learning (this may look familiar from the commit message to a patch I sent earlier):

  1. here is what "git pull $repo $branch" means
  2. here is a way to shorten it to "git pull $repo" (set up remote
     $repo)
  3. here is a way to shorten it to "git pull" (default to origin)

But I think there are people who will get to the list and say "why didn't you just tell me 'git pull' in the first place?" That is, the complaints we have seen in the past reveal _too many_ low level details too quickly.

Maybe we have stepped too far towards "top down workflow descriptions" and need to go back. I dunno.

Another way of thinking about it is that we need two sets of documentation with the same information (heresy, I know!): one bottom-up and one top-down. I think the manpages tend to be "bottom up" references. Bruce's user manual is more "top down" describing workflows. I wonder which one(s) Ingo read, and which helped the most.

-Peff
André Goddard Rosa· Apr 9, 2008, 23:56 UTC · re: Junio C Hamano · lore

Re: git annoyances

Show 9 quoted lines
>  > but it was a PITA and all of git's messages about the problem were not
>  > only unhelpful, they confused me into looking for problems where there
>  > were none IMO.
>
>  Yes, we need to teach "git" to do more mind-reading (I am not being
>  sarcastic).  There should be a pattern in common user errors that share
>  their roots to the same user misperception, and if we can identify that,
>  maybe we can make git guess what the user was really trying to do and give
>  better error messages than it currently does.
Something along the lines of:

Error description Why it happened How to solve/Sugestion

-- 
[]s,
André Goddard
Govind Salinas· Apr 10, 2008, 19:45 UTC · re: André Goddard Rosa · lore

Re: git annoyances

On Wed, Apr 9, 2008 at 6:56 PM, André Goddard Rosa <andre.goddard@gmail.com> wrote:

Show 16 quoted lines
> >  > but it was a PITA and all of git's messages about the problem were not
>  >  > only unhelpful, they confused me into looking for problems where there
>  >  > were none IMO.
>  >
>  >  Yes, we need to teach "git" to do more mind-reading (I am not being
>  >  sarcastic).  There should be a pattern in common user errors that share
>  >  their roots to the same user misperception, and if we can identify that,
>  >  maybe we can make git guess what the user was really trying to do and give
>  >  better error messages than it currently does.
>
>  Something along the lines of:
>
>  Error description
>  Why it happened
>  How to solve/Sugestion
>
Hi,

This actually touches on one of my main purposes behind Pyrite. I intend to do the following things to help the situation and I was wondering what the git community's reaction is.

1) Since it will be designed for end users I intend to remove the options not
designed for end users.  This will also shorten up the help so that the entire
help can be shown to the user when they encounter an error.
2) No unnamed options.  I think this would have helped the above case
although it would have required a *bit* more typing.  The command would
have looked like "pyt pull/fetch -r x86 -b latest"  Combined with the above
the command would have spit out the help and a message stating what was
missing.
3) No syntax.  Git has a lot of syntax.  It has refspecs, revision ranges,
symbolic names (although i do like these) that a user has to learn.  I
think this
is one of the most error prone parts of the git for new users.
Hopefully, I will
be able to find simple and straightforward ways for the user to supply
this info.
Any comments/suggestions will be appreciated.

Thanks, Govind.

Jean-Christian de Rivaz· Apr 10, 2008, 06:08 UTC · re: Junio C Hamano · lore

Re: git annoyances

Junio C Hamano a écrit :
Show 15 quoted lines
> That made us allowing the users to type "git pull" and "git fetch" without
> parameters.  This is generally a good thing: shorter to type for doing
> common things is always good, as long as the user knows what he is doing.
> 
> But at the same time, this allowed docs and cheat-sheets that mention only
> the form without parameters and not the normative "repository refspec"
> form.  This dumbed down the users not understand that in that context
> fetch (and pull, which is a fetch followed by a merge) is always happening
> against a single branch of single remote repository, the way to name
> remote repository and its branch(es) is to give them as separate
> parameters, and their not typing the pair explicitly is a mere convenience
> feature.  This particular aspect of the shorthand is actually very bad.
> It makes the mental model fuzzy, and hiding important rules of how the
> world works from new people would lead them to unnecessary confusion.  In
> short, we made it harder for the new people to "get" it.

A possible way it to, by default, make git print the full form of the command when a short form is used. So the user see the concept without having to read the documentation and learn it gradually. I personally like tools that act this way. It permit to make a basic and easy tutorial with short commands that let know the general concept and show the full potential of the tool.

A "short form" flag in a user (not repository) configuration file should allow to suppress the long form printout for the comfort of the users that don't want it.

-- Jean-Christian de Rivaz

Sverre Rabbelier· Apr 10, 2008, 08:19 UTC · re: Jean-Christian de Rivaz · lore

Re: git annoyances

On Thu, Apr 10, 2008 at 8:08 AM, Jean-Christian de Rivaz <jc@eclis.ch> wrote:
Show 6 quoted lines
>  A possible way it to, by default, make git print the full form of the
> command when a short form is used. So the user see the concept without
> having to read the documentation and learn it gradually. I personally like
> tools that act this way. It permit to make a basic and easy tutorial with
> short commands that let know the general concept and show the full potential
> of the tool.

I think this would be a very nice solution, not only do you allow the user to realize what it is they are doing, you also provide them with an easy way to be more verbose. Perhaps they wish to switch from the default short behavior to a somewhat different form (e.g., change a default 'master' argument to another branch). When writing out the full form each time the user gets an intuitive and gradual introduction into the rest of git, without limiting them or more advanced users.

>  A "short form" flag in a user (not repository) configuration file should
> allow to suppress the long form printout for the comfort of the users that
> don't want it.

Or perhaps, as I mentioned in the thread on "friendly refspecs", a "newbie" config option or command that turns on the informative verboseness options. As such, perhaps a "long form" flag would be more desired instead, to prevent existing developers from being spammed with information they do not are interested in.

Cheers,
Sverre Rabbelier
Ingo Molnar· Apr 10, 2008, 11:47 UTC · re: Ingo Molnar · lore

git-bisect annoyances

Ok, just in case i dont bore people with "stupid user" experiences and logs of sessions of confusion, here's another session i just had with Git.

This time it's with our good friend git-bisect - which i thought to master pretty well and which i already used successfully to bisect kernel bugs up to a hundred times already (at least).

The 'v' repository is a vanilla clone of Linus's upstream linux-2.6.git 
kernel tree with no other modifications done to it.
 
 dione:~> git-clone v linux-tmp4
 Initialized empty Git repository in /home/mingo/linux-tmp4/.git/
 0 blocks
 Checking out files: 100% (23809/23809), done.
 dione:~> cd linux-tmp4/
 dione:~/linux-tmp4> ls
 COPYING        MAINTAINERS     arch     fs       kernel  samples   usr
 CREDITS        Makefile        block    include  lib     scripts   virt
 Documentation  README          crypto   init     mm      security
 Kbuild         REPORTING-BUGS  drivers  ipc      net     sound
 #
 # ok, so far so good. done this a thousand times before.
 #
 # Now lets check out v2.6.24 and check whether the bug i'm interested 
 # in triggers on v2.6.24. I dont create an extra branch for it, because 
 # this is pure temporary work, i use a plain git-checkout as a 
 # throwaway temporary branch:
 #
 dione:~/linux-tmp4> git-checkout v2.6.24
 Note: moving to "v2.6.24" which isn't a local branch
 If you want to create a new branch from this checkout, you may do so
 (now or later) by using -b with the checkout command again. Example:
   git checkout -b <new_branch_name>
 HEAD is now at 4991408... Linux 2.6.24
 #
 # i build that kernel and boot it - the bug doesnt trigger - good. 
 # We've got all prerequisites for a bisection session - a 'good' kernel 
 # [v2.6.24] and a 'bad' kernel [HEAD].
 #
 #
 dione:~/linux-tmp4> git-bisect start
 fatal: ref HEAD is not a symbolic ref
 won't bisect on seeked tree
 #
 # Hm. It's not a symbolic ref, and git-bisect just wont do it. Ok but 
 # then what, and what can the user do to progress? It should be rather 
 # clear to Git what i'm intending to do here. I'm not interested in 
 # HEAD at all, i want to start bisection and i'll feed the good/bad 
 # points to git-bisect - once it lets me do that.
 #
 # Ok, lets see where we are:
 #
 dione:~/linux-tmp4> git-branch -a
 * (no branch)
   master
   origin/HEAD
   origin/master
   origin/new_branch
 #
 # So perhaps this new, unnamed branch is what is causing the trouble? 
 # Lets try a specific branch then:
 #
 dione:~/linux-tmp4> git-checkout master
 Previous HEAD position was 4991408... Linux 2.6.24
 Switched to branch "master"
 dione:~/linux-tmp4> git-bisect start
 won't bisect on seeked tree
 #
 # Hm, still no go. Lets see what git-bisect has to offer:
 #
 dione:~/linux-tmp4> git-bisect
 Usage: /usr/bin/git-bisect 
 [start|bad|good|skip|next|reset|visualize|replay|log|run]
 #
 # Ah, it has a reset thing, lets try it:
 #
 dione:~/linux-tmp4> git-bisect reset
 Note: moving to "49914084e797530d9baaf51df9eda77babc98fa8" which isn't a 
 local branch
 If you want to create a new branch from this checkout, you may do so
 (now or later) by using -b with the checkout command again. Example:
   git checkout -b <new_branch_name>
 HEAD is now at 4991408... Linux 2.6.24
 dione:~/linux-tmp4> git-bisect start
 fatal: ref HEAD is not a symbolic ref
 #
 # hm, still no go. I'm not interested in a new branch at all, but i 
 # want to bisect, so lets try what was suggested then and name the 
 # branch:
 #
 dione:~/linux-tmp4> git-checkout -b tmp
 Switched to a new branch "tmp"
 #
 # Looks good so far - can i bisect?
 #
 dione:~/linux-tmp4> git-bisect start
 won't bisect on seeked tree
 #
 # Hm, still no go. Ok, lets forget this whole temporary branch thing 
 # that looked good and try a more pristine state:
 #
 dione:~/linux-tmp4> git-checkout -b tmp2 master
 Previous HEAD position was 4991408... Linux 2.6.24
 Switched to a new branch "tmp2"
 dione:~/linux-tmp4> git-bisect start
 #
 # Halleluya! While i have typed much more than i wanted, and ended up 
 # with two extra branches that i have to throw away, it seems to be 
 # working! Although the command printing nothing is not really 
 # reassuring - did it really do something?
 #
 # Ok, lets get the bisection going now:
 #
 dione:~/linux-tmp4> git-bisect good v2.6.24 bad HEAD
 dione:~/linux-tmp4>
 #
 # Hm, no indication about what happened, and no "middle" bisection 
 # point offered. No way to figure out what's wrong.
 #
 # Ok, backtrack one more step - something's wrong here. Lets start 
 # again with a completely new tree:
 #
 dione:~> git-clone v linux-tmp5
 Initialized empty Git repository in /home/mingo/linux-tmp5/.git/
 0 blocks
 Checking out files: 100% (23809/23809), done.
 dione:~> cd linux-tmp5/
 dione:~/linux-tmp5> git-checkout -b tmp master
 Switched to a new branch "tmp"
 dione:~/linux-tmp5> git-bisect start good v2.6.24
 dione:~/linux-tmp5> cd
 dione:~> cd linux-tmp5/
 dione:~/linux-tmp5> git-bisect start good v2.6.24 bad master
 dione:~/linux-tmp5>
 #
 # Hm, nothing. Ho hum. Do i suck this much? One more tree than i wanted 
 # and three more branches that i wanted and still no bisection?
 #
 # Ah, i must have switched the arguments?
 #
 dione:~/linux-tmp5> git-bisect start v2.6.24 good master bad
 won't bisect on seeked tree
 #
 # Nope.
 #
 dione:~/linux-tmp5> git-bisect visualize
 You need to give me at least one good and one bad revisions.
 (You can use "git bisect bad" and "git bisect good" for that.)
 dione:~/linux-tmp5> git bisect bad HEAD
 dione:~/linux-tmp5> git bisect good v2.6.24
 Bisecting: -1 revisions left to test after this
 [eb36f4fc019835cecf0788907f6cab774508087b] fix oops on rmmod capidrv
 #
 # -1 revisions left to test? Ouch ...
 #
 # But why did "git bisect" make a difference to "git-bisect" ?
 # Lets see whether it's all from the same package:
 #
 dione:~> type git
 git is hashed (/usr/bin/git)
 dione:~> type git-bisect
 git-bisect is hashed (/usr/bin/git-bisect)
 dione:~> rpm -qf /usr/bin/git-bisect
 git-core-1.5.4.3-2.fc8
 dione:~> rpm -qf /usr/bin/git
 git-core-1.5.4.3-2.fc8
 #
 # Yup, it is. 20 minutes spent on this already and no bisection.
 # I really suck today :-)
 #
 #
 # So i started suspecting my kernel and my hardware. Are timestamps 
 # maybe messed up and confusing Git? Since the commands dont return 
 # success nor failure i was unsure what Git thought about my attempts.
 #
 # So i rebooted the box and created a new tree. No go.
 #
 #
 # Just to be sure i also waited through a full git-fsck, only 10 
 # minutes runtime:
 #
 dione:~/linux-tmp4> git-fsck --full --strict
 dangling commit f4be31ec9690cfe6e94fcbed6ae60a6a38b3c3ed
 dione:~/linux-tmp4>
 #
 # [ Sidenote #1: git-fsck is such a heavy operation that it should 
 #   really return some indication by default that it's all appears OK.
 #   A user typically only runs git-fsck if in deep doubt about some 
 #   git detail - so while silence is often good for a comment, it's 
 #   counter-intuitive here. Especially since the "breakage" of 
 #   git-bisect is "silence" too, so the user is unable to trust these 
 #   different modal forms of silence and gets frustrated ... ]
 #
 #
 # [ Sidenote #2: git-fsck --full --strict is slow and we always knew
 #   this - it's a last-ditch thing for the truly hopeless. But this is 
 #   a 3.2 GHz quad box that is only 25% utilized during git-fsck but 
 #   takes 10 minutes to finish. Presumably git-fsck could run multiple 
 #   threads/tasks to be sped up? Making the slowest possible operation 
 #   of a tool significantly faster is a good way to reduce user 
 #   frustration IMO. A user is already frustrated enough when he tries 
 #   --full --strict. And i _bet_ a parallel version of git-fsck would 
 #   also be an fantastic bad-RAM checker ;-) ]
 #
 #
 # Then, many other silly attempts later and at linux-tmp8, by chance - 
 # 30 minutes down the line - i got it going:
 #
 # I updated my Linus tree on the (rather pathetic) theory that maybe a 
 # specific layout of the repo breaks bisection - and that seems to have 
 # made a difference:
 #
 dione:~/linux-tmp8> git-checkout -b tmp2 master
 Switched to a new branch "tmp2"
 dione:~/linux-tmp8> git-bisect start
 won't bisect on seeked tree
 dione:~/linux-tmp8> git-bisect reset
 Switched to branch "master"
 dione:~/linux-tmp8> git-bisect bad master
 You need to start by "git bisect start"
 Do you want me to do it for you [Y/n]? Y
 dione:~/linux-tmp8> git-bisect good v2.6.24
 Bisecting: 6270 revisions left to test after this
 [4814bdbd590e835ecec2d5e505165ec1c19796b2] [NETNS]: Lookup in FIB 
 semantic hashes taking into account the namespace.
 #
 # But i dont understand why. Before updating Linus's tree i saved away 
 # the commit ID that showed the breakage, just in case it matters:
 #
 commit 7180c4c9e09888db0a188f729c96c6d7bd61fa83
 Merge: 4c3b01f... 869ab51...
 Author: Linus Torvalds <torvalds@linux-foundation.org>
 Date:   Mon Apr 7 19:15:35 2008 -0700
 #
 # .. but couldnt reproduce this weirdness with specifically checking 
 # out 7180c4c9e09888db0a188f729c96c6d7bd61fa83. But i still have the 
 # linux-tmp4 repository that shows this behavior reliably. It's all 
 # quite weird. Either this repo is corrupted in some special way, or my 
 # hardware has some really strange runtime failure, or i'm missing 
 # something very obvious ;-)
 #
 #
 # One more minor sidenote. Git-bisect creates its own branch:
 #
 dione:~/linux-tmp12> git-branch -a
 * bisect
   master
   tmp
   tmp2
   origin/HEAD
   origin/master
   origin/new_branch
 #
 # So i assumed that i could get rid of that 'bisect' branch by doing 
 # the obvious: "git-bisect stop", but no go:
 #
  dione:~/linux-tmp12> git-bisect stop
  Usage: /usr/bin/git-bisect [start|bad|good|skip|next|reset|visualize|replay|log|run]
 #
 # After some experimentation "git-bisect reset" did the trick - but 
 # it's a bit counter-intuitive IMO, because the logical extension of 
 # 'start' is 'stop', and i often use 'git-bisect reset' to just restart
 # bisection anew. (it chimes in on 'restart')
 #
 #
 # Ok, that's all for today. :-)
 #
	Ingo
Christian Couder· Apr 11, 2008, 05:41 UTC · re: Ingo Molnar · lore

Re: git-bisect annoyances

Le jeudi 10 avril 2008, Ingo Molnar a écrit :
> Ok, just in case i dont bore people with "stupid user" experiences and
> logs of sessions of confusion, here's another session i just had with
> Git.
Thanks, this is very much appreciated.
Show 44 quoted lines
> This time it's with our good friend git-bisect - which i thought to
> master pretty well and which i already used successfully to bisect
> kernel bugs up to a hundred times already (at least).
>
> The 'v' repository is a vanilla clone of Linus's upstream linux-2.6.git
> kernel tree with no other modifications done to it.
>
>  dione:~> git-clone v linux-tmp4
>  Initialized empty Git repository in /home/mingo/linux-tmp4/.git/
>  0 blocks
>  Checking out files: 100% (23809/23809), done.
>  dione:~> cd linux-tmp4/
>  dione:~/linux-tmp4> ls
>  COPYING        MAINTAINERS     arch     fs       kernel  samples   usr
>  CREDITS        Makefile        block    include  lib     scripts   virt
>  Documentation  README          crypto   init     mm      security
>  Kbuild         REPORTING-BUGS  drivers  ipc      net     sound
>
>  #
>  # ok, so far so good. done this a thousand times before.
>  #
>  # Now lets check out v2.6.24 and check whether the bug i'm interested
>  # in triggers on v2.6.24. I dont create an extra branch for it, because
>  # this is pure temporary work, i use a plain git-checkout as a
>  # throwaway temporary branch:
>  #
>
>  dione:~/linux-tmp4> git-checkout v2.6.24
>  Note: moving to "v2.6.24" which isn't a local branch
>  If you want to create a new branch from this checkout, you may do so
>  (now or later) by using -b with the checkout command again. Example:
>    git checkout -b <new_branch_name>
>  HEAD is now at 4991408... Linux 2.6.24
>
>  #
>  # i build that kernel and boot it - the bug doesnt trigger - good.
>  # We've got all prerequisites for a bisection session - a 'good' kernel
>  # [v2.6.24] and a 'bad' kernel [HEAD].
>  #
>  #
>
>  dione:~/linux-tmp4> git-bisect start
>  fatal: ref HEAD is not a symbolic ref
>  won't bisect on seeked tree

Yeah, it seems that this is a left over from cogito. There has been some work on it lately but it seems not enough. See:

http://git.kernel.org/?p=git/git.git;a=commitdiff;h=0f497e75f05cdf0c0c1278eaba898cda6f118d71
Show 28 quoted lines
>  #
>  # Hm. It's not a symbolic ref, and git-bisect just wont do it. Ok but
>  # then what, and what can the user do to progress? It should be rather
>  # clear to Git what i'm intending to do here. I'm not interested in
>  # HEAD at all, i want to start bisection and i'll feed the good/bad
>  # points to git-bisect - once it lets me do that.
>  #
>  # Ok, lets see where we are:
>  #
>
>  dione:~/linux-tmp4> git-branch -a
>  * (no branch)
>    master
>    origin/HEAD
>    origin/master
>    origin/new_branch
>
>  #
>  # So perhaps this new, unnamed branch is what is causing the trouble?
>  # Lets try a specific branch then:
>  #
>
>  dione:~/linux-tmp4> git-checkout master
>  Previous HEAD position was 4991408... Linux 2.6.24
>  Switched to branch "master"
>
>  dione:~/linux-tmp4> git-bisect start
>  won't bisect on seeked tree
This seems to work for me with git 1.5.5 on the git tree:

$ git checkout master Switched to branch "master" Your branch is ahead of the tracked remote branch 'origin/master' by 4 commits. $ git bisect start $

What git version do you have ?
Show 22 quoted lines
>  #
>  # Hm, still no go. Lets see what git-bisect has to offer:
>  #
>
>  dione:~/linux-tmp4> git-bisect
>  Usage: /usr/bin/git-bisect
>  [start|bad|good|skip|next|reset|visualize|replay|log|run]
>
>  #
>  # Ah, it has a reset thing, lets try it:
>  #
>
>  dione:~/linux-tmp4> git-bisect reset
>  Note: moving to "49914084e797530d9baaf51df9eda77babc98fa8" which isn't a
>  local branch
>  If you want to create a new branch from this checkout, you may do so
>  (now or later) by using -b with the checkout command again. Example:
>    git checkout -b <new_branch_name>
>  HEAD is now at 4991408... Linux 2.6.24
>
>  dione:~/linux-tmp4> git-bisect start
>  fatal: ref HEAD is not a symbolic ref
This probably come from previous failures.
Show 15 quoted lines
>  #
>  # hm, still no go. I'm not interested in a new branch at all, but i
>  # want to bisect, so lets try what was suggested then and name the
>  # branch:
>  #
>
>  dione:~/linux-tmp4> git-checkout -b tmp
>  Switched to a new branch "tmp"
>
>  #
>  # Looks good so far - can i bisect?
>  #
>
>  dione:~/linux-tmp4> git-bisect start
>  won't bisect on seeked tree
This too.
Show 22 quoted lines
>  #
>  # Hm, still no go. Ok, lets forget this whole temporary branch thing
>  # that looked good and try a more pristine state:
>  #
>
>  dione:~/linux-tmp4> git-checkout -b tmp2 master
>  Previous HEAD position was 4991408... Linux 2.6.24
>  Switched to a new branch "tmp2"
>
>  dione:~/linux-tmp4> git-bisect start
>
>  #
>  # Halleluya! While i have typed much more than i wanted, and ended up
>  # with two extra branches that i have to throw away, it seems to be
>  # working! Although the command printing nothing is not really
>  # reassuring - did it really do something?
>  #
>  # Ok, lets get the bisection going now:
>  #
>
>  dione:~/linux-tmp4> git-bisect good v2.6.24 bad HEAD
>  dione:~/linux-tmp4>

This is really bad, because, as you can see from the man page or "git bisect -h" (see also the patch I just sent), "git bisect good" can take many known good revisions:

git bisect good [<rev>...]
        mark <rev>... known-good revisions.
So you marked also "bad" and HEAD as "good".
This is really strange, because here I get for example:

$ git-bisect good bad HEAD Bad rev input: bad HEAD

So you must have something tagged as "bad" or have a "bad" branch, and that's why the command works for you but does the wrong thing.

If you wanted to do it all in one command you could have done:
$ git bisect start HEAD v2.6.24
That would have marked HEAD as "bad" and v2.6.24 as "good":
git bisect start [<bad> [<good>...]] [--] [<pathspec>...]
        reset bisect state and start bisection.
>  #
>  # Hm, no indication about what happened, and no "middle" bisection
>  # point offered. No way to figure out what's wrong.

Right, we probably need to have at look at this more closely, maybe warn if a "bad" or a "good" tag or branch exists or something like that.

Show 12 quoted lines
>  # Ok, backtrack one more step - something's wrong here. Lets start
>  # again with a completely new tree:
>  #
>
>  dione:~> git-clone v linux-tmp5
>  Initialized empty Git repository in /home/mingo/linux-tmp5/.git/
>  0 blocks
>  Checking out files: 100% (23809/23809), done.
>  dione:~> cd linux-tmp5/
>  dione:~/linux-tmp5> git-checkout -b tmp master
>  Switched to a new branch "tmp"
>  dione:~/linux-tmp5> git-bisect start good v2.6.24
This marked "good" as "bad" and "v2.6.24" as "good".

Again this should "work" only if you have a "good" tag or branch in your repo.

>  dione:~/linux-tmp5> cd
>  dione:~> cd linux-tmp5/
>  dione:~/linux-tmp5> git-bisect start good v2.6.24 bad master
This marked "good" as "bad", and "v2.6.24", "bad" and "master" as "good".
Show 11 quoted lines
>  dione:~/linux-tmp5>
>
>  #
>  # Hm, nothing. Ho hum. Do i suck this much? One more tree than i wanted
>  # and three more branches that i wanted and still no bisection?
>  #
>  # Ah, i must have switched the arguments?
>  #
>
>  dione:~/linux-tmp5> git-bisect start v2.6.24 good master bad
>  won't bisect on seeked tree

This marked "v2.6.24" as "bad", and "good", "master" and "bad" as "good". So it's wrong too.

Show 11 quoted lines
>  #
>  # Nope.
>  #
>
>  dione:~/linux-tmp5> git-bisect visualize
>  You need to give me at least one good and one bad revisions.
>  (You can use "git bisect bad" and "git bisect good" for that.)
>  dione:~/linux-tmp5> git bisect bad HEAD
>  dione:~/linux-tmp5> git bisect good v2.6.24
>  Bisecting: -1 revisions left to test after this
>  [eb36f4fc019835cecf0788907f6cab774508087b] fix oops on rmmod capidrv

That's much better but you didn't "reset" or "start" again before giving it correctly the good and bad revs, so there are still some wrong left over from your previous start above.

>  #
>  # -1 revisions left to test? Ouch ...
>  #
>  # But why did "git bisect" make a difference to "git-bisect" ?
It should not have made any difference.
Show 43 quoted lines
>  # Lets see whether it's all from the same package:
>  #
>
>  dione:~> type git
>  git is hashed (/usr/bin/git)
>  dione:~> type git-bisect
>  git-bisect is hashed (/usr/bin/git-bisect)
>  dione:~> rpm -qf /usr/bin/git-bisect
>  git-core-1.5.4.3-2.fc8
>  dione:~> rpm -qf /usr/bin/git
>  git-core-1.5.4.3-2.fc8
>
>  #
>  # Yup, it is. 20 minutes spent on this already and no bisection.
>  # I really suck today :-)
>  #
>
>  #
>  # So i started suspecting my kernel and my hardware. Are timestamps
>  # maybe messed up and confusing Git? Since the commands dont return
>  # success nor failure i was unsure what Git thought about my attempts.
>  #
>  # So i rebooted the box and created a new tree. No go.
>  #
>
>  #
>  # Just to be sure i also waited through a full git-fsck, only 10
>  # minutes runtime:
>  #
>
>  dione:~/linux-tmp4> git-fsck --full --strict
>  dangling commit f4be31ec9690cfe6e94fcbed6ae60a6a38b3c3ed
>  dione:~/linux-tmp4>
>
>  #
>  # [ Sidenote #1: git-fsck is such a heavy operation that it should
>  #   really return some indication by default that it's all appears OK.
>  #   A user typically only runs git-fsck if in deep doubt about some
>  #   git detail - so while silence is often good for a comment, it's
>  #   counter-intuitive here. Especially since the "breakage" of
>  #   git-bisect is "silence" too, so the user is unable to trust these
>  #   different modal forms of silence and gets frustrated ... ]
>  #

I cannot comment on "git fsck" but I think it has nothing to do with bisect "breakages".

Show 37 quoted lines
>  #
>  # [ Sidenote #2: git-fsck --full --strict is slow and we always knew
>  #   this - it's a last-ditch thing for the truly hopeless. But this is
>  #   a 3.2 GHz quad box that is only 25% utilized during git-fsck but
>  #   takes 10 minutes to finish. Presumably git-fsck could run multiple
>  #   threads/tasks to be sped up? Making the slowest possible operation
>  #   of a tool significantly faster is a good way to reduce user
>  #   frustration IMO. A user is already frustrated enough when he tries
>  #   --full --strict. And i _bet_ a parallel version of git-fsck would
>  #   also be an fantastic bad-RAM checker ;-) ]
>  #
>
>  #
>  # Then, many other silly attempts later and at linux-tmp8, by chance -
>  # 30 minutes down the line - i got it going:
>  #
>  # I updated my Linus tree on the (rather pathetic) theory that maybe a
>  # specific layout of the repo breaks bisection - and that seems to have
>  # made a difference:
>  #
>
>  dione:~/linux-tmp8> git-checkout -b tmp2 master
>  Switched to a new branch "tmp2"
>  dione:~/linux-tmp8> git-bisect start
>  won't bisect on seeked tree
>  dione:~/linux-tmp8> git-bisect reset
>  Switched to branch "master"
>  dione:~/linux-tmp8> git-bisect bad master
>  You need to start by "git bisect start"
>  Do you want me to do it for you [Y/n]? Y
>  dione:~/linux-tmp8> git-bisect good v2.6.24
>  Bisecting: 6270 revisions left to test after this
>  [4814bdbd590e835ecec2d5e505165ec1c19796b2] [NETNS]: Lookup in FIB
>  semantic hashes taking into account the namespace.
>
>  #
>  # But i dont understand why.
I hope you understand better now.
Show 46 quoted lines
>  # Before updating Linus's tree i saved away 
>  # the commit ID that showed the breakage, just in case it matters:
>  #
>
>  commit 7180c4c9e09888db0a188f729c96c6d7bd61fa83
>  Merge: 4c3b01f... 869ab51...
>  Author: Linus Torvalds <torvalds@linux-foundation.org>
>  Date:   Mon Apr 7 19:15:35 2008 -0700
>
>  #
>  # .. but couldnt reproduce this weirdness with specifically checking
>  # out 7180c4c9e09888db0a188f729c96c6d7bd61fa83. But i still have the
>  # linux-tmp4 repository that shows this behavior reliably. It's all
>  # quite weird. Either this repo is corrupted in some special way, or my
>  # hardware has some really strange runtime failure, or i'm missing
>  # something very obvious ;-)
>  #
>
>  #
>  # One more minor sidenote. Git-bisect creates its own branch:
>  #
>
>  dione:~/linux-tmp12> git-branch -a
>  * bisect
>    master
>    tmp
>    tmp2
>    origin/HEAD
>    origin/master
>    origin/new_branch
>
>  #
>  # So i assumed that i could get rid of that 'bisect' branch by doing
>  # the obvious: "git-bisect stop", but no go:
>  #
>
>   dione:~/linux-tmp12> git-bisect stop
>   Usage: /usr/bin/git-bisect
> [start|bad|good|skip|next|reset|visualize|replay|log|run]
>
>  #
>  # After some experimentation "git-bisect reset" did the trick - but
>  # it's a bit counter-intuitive IMO, because the logical extension of
>  # 'start' is 'stop', and i often use 'git-bisect reset' to just restart
>  # bisection anew. (it chimes in on 'restart')
>  #

"git bisect start" also does a "restart" if a bisect is already started. But yes, we could add "stop" as a synonym for "reset" and "restart" as a synonym for "start".

Thanks, Christian.

Show 9 quoted lines
>  #
>  # Ok, that's all for today. :-)
>  #
>
> 	Ingo
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ingo Molnar· Apr 11, 2008, 11:41 UTC · re: Christian Couder · lore

Re: git-bisect annoyances

* Christian Couder <chriscool@tuxfamily.org> wrote:
Show 13 quoted lines
> >  #
> >  # So perhaps this new, unnamed branch is what is causing the trouble?
> >  # Lets try a specific branch then:
> >  #
> >
> >  dione:~/linux-tmp4> git-checkout master
> >  Previous HEAD position was 4991408... Linux 2.6.24
> >  Switched to branch "master"
> >
> >  dione:~/linux-tmp4> git-bisect start
> >  won't bisect on seeked tree
> 
> This seems to work for me with git 1.5.5 on the git tree:
> What git version do you have ?
git-core-1.5.4.3-2.fc8, like for the previous report.

and it worked for me too in a later tree - so the condition seems transient.

Show 19 quoted lines
> >  dione:~/linux-tmp4> git-bisect good v2.6.24 bad HEAD
> >  dione:~/linux-tmp4>
> 
> This is really bad, because, as you can see from the man page or "git 
> bisect -h" (see also the patch I just sent), "git bisect good" can 
> take many known good revisions:
> 
> git bisect good [<rev>...]
>         mark <rev>... known-good revisions.
> 
> So you marked also "bad" and HEAD as "good".
> 
> This is really strange, because here I get for example:
> 
> $ git-bisect good bad HEAD
> Bad rev input: bad HEAD
> 
> So you must have something tagged as "bad" or have a "bad" branch, and 
> that's why the command works for you but does the wrong thing.
no, there are no 'bad' braches or revisions.

and ... if "git-bisect good X bad Y" is invalid syntax it should be detected by the tool ... I did not think up that syntax myself, i think i saw it somewhere else mentioned by someone and found it logical. Weird. Generally i do use the separate commands though.

Show 18 quoted lines
> >  dione:~/linux-tmp5> git-bisect visualize
> >  You need to give me at least one good and one bad revisions.
> >  (You can use "git bisect bad" and "git bisect good" for that.)
> >  dione:~/linux-tmp5> git bisect bad HEAD
> >  dione:~/linux-tmp5> git bisect good v2.6.24
> >  Bisecting: -1 revisions left to test after this
> >  [eb36f4fc019835cecf0788907f6cab774508087b] fix oops on rmmod capidrv
> 
> That's much better but you didn't "reset" or "start" again before 
> giving it correctly the good and bad revs, so there are still some 
> wrong left over from your previous start above.
> 
> >  #
> >  # -1 revisions left to test? Ouch ...
> >  #
> >  # But why did "git bisect" make a difference to "git-bisect" ?
> 
> It should not have made any difference.

it probably didnt - i was just grasping at straws because there was no reassuring feedback about what happened so my confidence about my _assumptions_ what was happening in the background gradually eroded so i went in larger and larger circles around the problem dropping more and more assumptions and re-checking them.

But i pasted this directly from that session so the "-1" is definitely not imaginery and it is anomalous.

	Ingo
Christian Couder· Apr 12, 2008, 06:56 UTC · re: Ingo Molnar · lore

Re: git-bisect annoyances

Le vendredi 11 avril 2008, Ingo Molnar a écrit :
Show 21 quoted lines
> * Christian Couder <chriscool@tuxfamily.org> wrote:
> > >  #
> > >  # So perhaps this new, unnamed branch is what is causing the
> > > trouble? # Lets try a specific branch then:
> > >  #
> > >
> > >  dione:~/linux-tmp4> git-checkout master
> > >  Previous HEAD position was 4991408... Linux 2.6.24
> > >  Switched to branch "master"
> > >
> > >  dione:~/linux-tmp4> git-bisect start
> > >  won't bisect on seeked tree
> >
> > This seems to work for me with git 1.5.5 on the git tree:
> >
> > What git version do you have ?
>
> git-core-1.5.4.3-2.fc8, like for the previous report.
>
> and it worked for me too in a later tree - so the condition seems
> transient.

Yes, it probably depends on what you have done before. I didn't look at it yet, but I will have a look soon. Anyway as Junio said, there have been some improvements in 1.5.5 so it might be a good idea to upgrade.

Show 21 quoted lines
> > >  dione:~/linux-tmp4> git-bisect good v2.6.24 bad HEAD
> > >  dione:~/linux-tmp4>
> >
> > This is really bad, because, as you can see from the man page or "git
> > bisect -h" (see also the patch I just sent), "git bisect good" can
> > take many known good revisions:
> >
> > git bisect good [<rev>...]
> >         mark <rev>... known-good revisions.
> >
> > So you marked also "bad" and HEAD as "good".
> >
> > This is really strange, because here I get for example:
> >
> > $ git-bisect good bad HEAD
> > Bad rev input: bad HEAD
> >
> > So you must have something tagged as "bad" or have a "bad" branch, and
> > that's why the command works for you but does the wrong thing.
>
> no, there are no 'bad' braches or revisions.
You are right, we have got some bugs here I think.

In my case bad and HEAD were neither proper revs, that's why I got an error. But I realized that as long as there is one proper rev in what you give to "git bisect good" it will ignore bad revs and mark as good the proper rev you gave it.

I just sent a patch to fix this, but I am not sure it's the right fix. More work is probably needed. Ooops I just spotted one bug in my patch. Please wait, I will send another one.

> and ... if "git-bisect good X bad Y" is invalid syntax it should be
> detected by the tool ... 
Yes.

Thanks again, Christian.

Junio C Hamano· Apr 11, 2008, 05:56 UTC · re: Ingo Molnar · lore

Re: git-bisect annoyances

Ingo Molnar <mingo@elte.hu> writes:
Show 6 quoted lines
>  dione:~/linux-tmp4> git-bisect start
>  fatal: ref HEAD is not a symbolic ref
>  won't bisect on seeked tree
>
>  #
>  # Hm. It's not a symbolic ref, and git-bisect just wont do it.

Enough people were unhappy with this historical wart and we stopped refusing to "bisect on seeked tree" since b577bb9 (Eliminate confusing "won't bisect on seeked tree" failure, 2008-02-23); you should find it as part of the 1.5.5 release.

The disturbing "fatal: ref HEAD not a symref" is still there even though it should be harmless. The message should be squelched.

Gabriel· Apr 10, 2008, 23:25 UTC · re: Ingo Molnar · lore

[PATCH] When a remote is added but not fetched, tell the user.

A helpful message tells the user when a remote was added without being fetched, and how to fetch it.

Our default of not fetching is breaking the users' workflow in the common "let me access this repo" use case. This message alleviates the problem.

Signed-off-by: Gabriel <g2p.code@gmail.com>
---
 builtin-remote.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index d77f10a..044215a 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -111,8 +111,16 @@ static int add(int argc, const char **argv)
 			return 1;
 	}
 
-	if (fetch && fetch_remote(name))
-		return 1;
+	if (fetch) {
+		if (fetch_remote(name))
+			return 1;
+	}
+	else {
+		printf ("Added remote repository `%s' without fetching it.\n"
+			"Before accessing the branches of this "
+			"remote, run `git fetch %s' "
+			"or `git remote update'.\n", name, name);
+	}
 
 	if (master) {
 		strbuf_reset(&buf);
-- 
1.5.5.24.geb27
Johannes Schindelin· Apr 11, 2008, 15:21 UTC · re: Gabriel · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

Hi,
On Fri, 11 Apr 2008, Gabriel wrote:
Show 5 quoted lines
> +	else {
> +		printf ("Added remote repository `%s' without fetching it.\n"
> +			"Before accessing the branches of this "
> +			"remote, run `git fetch %s' "
> +			"or `git remote update'.\n", name, name);

Is this really, really necessary? I was quite happy when a few people made Git less chatty, recently.

Ciao, Dscho

Gabriel· Apr 11, 2008, 18:35 UTC · re: Johannes Schindelin · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

Le Fri, 11 Apr 2008 16:21:45 +0100 (BST), Johannes Schindelin <Johannes.Schindelin@gmx.de> a écrit :

> Hi,
Hi
Show 11 quoted lines
> On Fri, 11 Apr 2008, Gabriel wrote:
> 
> > +	else {
> > +		printf ("Added remote repository `%s' without
> > fetching it.\n"
> > +			"Before accessing the branches of this "
> > +			"remote, run `git fetch %s' "
> > +			"or `git remote update'.\n", name, name);
> 
> Is this really, really necessary?  I was quite happy when a few
> people made Git less chatty, recently.
Not necessary, but a real usability improvement.

I think the transcript that started the thread makes it clear that having "git remote add" not fetching is not the right default. The user wants to use a remote repository, and has learned these are called "remotes". So he does not have too much trouble finding/remembering the command "git remote add <name> <url>". Now with the user's goal in mind, it makes no sense to add a remote and then not fetch it, because the user definitely wants to do something with the remote. By not fetching it, we are surprising the user (this is apparent in the transcript), maybe we are making him go through some documentation, and he will have to go through a mental checklist "did I add the remote? yes. did I fetch it? yes" later on.

The best solution is a patch that makes --fetch default to yes for git remote add and discuss that.

In case the remote wasn't fetched, adding some documentation at a place where it _will_ be needed does no harm. This is not an operation as frequent as git status or git checkout, so the three lines it takes in a terminal aren't expensive. A more experienced user that usually runs "git remote add -f", will not see it either.

-- 
Gabriel
Gabriel· Apr 11, 2008, 18:39 UTC · re: Gabriel · lore

[PATCH] Default to fetching a remote after adding it.

This is what the user wants in 99% of cases.
Signed-off-by: Gabriel <g2p.code@gmail.com>
---
 Documentation/git-remote.txt |    4 ++--
 builtin-remote.c             |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 2cbd1f7..04de972 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git-remote'
-'git-remote' add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
+'git-remote' add [-t <branch>] [-m <master>] [--no-fetch] [--mirror] <name> <url>
 'git-remote' rm <name>
 'git-remote' show <name>
 'git-remote' prune <name>
@@ -34,7 +34,7 @@ Adds a remote named <name> for the repository at
 <url>.  The command `git fetch <name>` can then be used to create and
 update remote-tracking branches <name>/<branch>.
 +
-With `-f` option, `git fetch <name>` is run immediately after
+Without the `--no-fetch` option, `git fetch <name>` is run immediately after
 the remote information is set up.
 +
 With `-t <branch>` option, instead of the default glob
diff --git a/builtin-remote.c b/builtin-remote.c
index 044215a..c0d7d96 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -54,7 +54,7 @@ static int fetch_remote(const char *name)
 
 static int add(int argc, const char **argv)
 {
-	int fetch = 0, mirror = 0;
+	int fetch = 1, mirror = 0;
 	struct path_list track = { NULL, 0, 0 };
 	const char *master = NULL;
 	struct remote *remote;
-- 
1.5.5.25.g17ee
Stephen Sinclair· Apr 11, 2008, 19:17 UTC · re: Gabriel · lore

Re: [PATCH] Default to fetching a remote after adding it.

On Fri, Apr 11, 2008 at 2:39 PM, Gabriel <g2p.code@gmail.com> wrote:
> This is what the user wants in 99% of cases.

Where did you get these magical statistics? I, for one, have never expected this behaviour.

Steve
Johannes Schindelin· Apr 12, 2008, 14:33 UTC · re: Gabriel · lore

Re: [PATCH] Default to fetching a remote after adding it.

Hi,
On Fri, 11 Apr 2008, Gabriel wrote:
> This is what the user wants in 99% of cases.

This is wrong, at least in my experience. Do not make up statistics if you want to be taken seriously.

Ciao, Dscho

Gabriel· Apr 12, 2008, 15:13 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Default to fetching a remote after adding it.

On Sat, 12 Apr 2008 15:33:30 +0100 (BST), Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:

Show 8 quoted lines
> Hi,
> 
> On Fri, 11 Apr 2008, Gabriel wrote:
> 
> > This is what the user wants in 99% of cases.
> 
> This is wrong, at least in my experience.  Do not make up statistics
> if you want to be taken seriously.

This is obviously not a real statistic, and poor wording on my part. It was meant to summarise the justification that I gave in the parent mail; that justification was certainly up to discussion, and it turns out I was wrong.

Which leaves us with the other suggestion of the previous patch, that others have discussed. Now that we have the maintainer's opinion, this is also settled.

Anyway, it's easy to get into subjective arguments on usability, and I'll be more careful about this. Which shouldn't prevent us from improving git usability.

Johannes Schindelin· Apr 12, 2008, 15:24 UTC · re: Gabriel · lore

Re: [PATCH] Default to fetching a remote after adding it.

Hi,
On Sat, 12 Apr 2008, Gabriel wrote:
> Now that we have the maintainer's opinion, this is also settled.
Thanks for ignoring my opinion.

Have a nice life, Dscho

Teemu Likonen· Apr 11, 2008, 19:08 UTC · re: Gabriel · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

Gabriel wrote (2008-04-11 20:35 +0200):
Show 8 quoted lines
> I think the transcript that started the thread makes it clear that
> having "git remote add" not fetching is not the right default. The
> user wants to use a remote repository, and has learned these are
> called "remotes". So he does not have too much trouble
> finding/remembering the command "git remote add <name> <url>". Now
> with the user's goal in mind, it makes no sense to add a remote and
> then not fetch it, because the user definitely wants to do something
> with the remote. By not fetching it, we are surprising the user 

Hmm, I'm quite newbie but I have never expected "git remote add" to fetch anything. I wouldn't want it to do it automatically. From the beginning I saw "git remote" as a _configuration_ tool. No doubt it's common to fetch after configuring a remote but in my mind they are two logically different steps (configure, fetch/pull) which I think should be kept separate. Once I have configured something I may want to check that I did the right thing, then configure some more remotes and maybe fetch tomorrow. Maybe I don't want to fetch at all but only pull from that remote. So let's not build ready workflows for users, only convenient, logical tools.

That said, I don't mind short messages like "use 'git fetch' to obtain branches" but I don't think that is necessary.

Junio C Hamano· Apr 11, 2008, 21:39 UTC · re: Teemu Likonen · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

Teemu Likonen <tlikonen@iki.fi> writes:
Show 14 quoted lines
> Gabriel wrote (2008-04-11 20:35 +0200):
>
>> I think the transcript that started the thread makes it clear that
>> having "git remote add" not fetching is not the right default. The
>> user wants to use a remote repository, and has learned these are
>> called "remotes". So he does not have too much trouble
>> finding/remembering the command "git remote add <name> <url>". Now
>> with the user's goal in mind, it makes no sense to add a remote and
>> then not fetch it, because the user definitely wants to do something
>> with the remote. By not fetching it, we are surprising the user 
>
> Hmm, I'm quite newbie but I have never expected "git remote add" to
> fetch anything. I wouldn't want it to do it automatically. From the
> beginning I saw "git remote" as a _configuration_ tool.
Good student ;-).

Not only that fetch-after-add is _not_ a common nor majority thing at all (contrary to what Gabriel assumed), the "fetch" step is conceptually an unrelated operation from the primary point of "remote add"; "-f" option is a mere convenience feature and we stop at making it conveniently available, never making it a default nor overly advertising it.

If the user tells you not to fetch, the command should not bother the user with excess messages, unless the user explicitly asks to, either.

Sverre Rabbelier· Apr 11, 2008, 22:35 UTC · re: Junio C Hamano · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

On Fri, Apr 11, 2008 at 11:39 PM, Junio C Hamano <gitster@pobox.com> wrote:
>  If the user tells you not to fetch, the command should not bother the user
>  with excess messages, unless the user explicitly asks to, either.

I fully agree here, but is there a way for the user to do so? Especially the beginning user? Perhaps in the form of a -v(erbose) switch, but for that to be useful it would have to be present across most/all commands and have the same (type of) result. That is, it should provide the user with additional information on what they did wrong/what they likely want to do from here. In this case though I agree that, as Teemu pointed out, 'git remote add' is a config tool. 'man git remote add' points this out more than clearly enough for regular use. Maybe keep it in mind for the to-be "git mind reading" functionality.

Cheers,
Sverre Rabbelier
Junio C Hamano· Apr 11, 2008, 23:15 UTC · re: Sverre Rabbelier · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

"Sverre Rabbelier" <alturin@gmail.com> writes:
Show 7 quoted lines
> On Fri, Apr 11, 2008 at 11:39 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>  If the user tells you not to fetch, the command should not bother the user
>>  with excess messages, unless the user explicitly asks to, either.
>
> I fully agree here, but is there a way for the user to do so?
> Especially the beginning user? Perhaps in the form of a -v(erbose)
> switch,...

Yeah, I am not sure if that should be called --verbose, but a "training wheel" mode of operation somebody else mentioned the other day that echoes back what the command thinks it was told to do by the user, together with help text that explains what other things the user could have told to the command to enrich its operation, might be an interesting addition.

Sverre Rabbelier· Apr 11, 2008, 23:20 UTC · re: Junio C Hamano · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

On Sat, Apr 12, 2008 at 1:15 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 5 quoted lines
>  Yeah, I am not sure if that should be called --verbose, but a "training
>  wheel" mode of operation somebody else mentioned the other day that echoes
>  back what the command thinks it was told to do by the user, together with
>  help text that explains what other things the user could have told to the
>  command to enrich its operation, might be an interesting addition.
Hmmm, I'm not sure about '--verbose' as a name either, but it -is-
usually used to display more information about the command(s) being
executed. E.g.:
-v, --verbose
	      explain what is being done
http://unixhelp.ed.ac.uk/CGI/man-cgi?mv
Sounds pretty much like what we're doing, explaining what command we
thing is being executed. The extra text OTOH with 'possible other
workflow suggestions' doesn't quite fit in the '--verbose' picture.
Perhaps a different kind of command, like '--newbie' (or, less
humiliating, '--explain') would be more appropriate.
Miles Bader· Apr 15, 2008, 03:15 UTC · re: Teemu Likonen · lore

Re: [PATCH] When a remote is added but not fetched, tell the user.

Teemu Likonen <tlikonen@iki.fi> writes:
> Hmm, I'm quite newbie but I have never expected "git remote add" to
> fetch anything. I wouldn't want it to do it automatically.
I agree.
An automatic fetch would be ... surprising.
-Miles
-- 
"Don't just question authority,
Don't forget to question me."
-- Jello Biafra
Gabriel· Apr 11, 2008, 19:29 UTC · re: Gabriel · lore

[PATCH] Default to fetching a remote after adding it.

This is what the user wants in 99% of cases.
Signed-off-by: Gabriel <g2p.code@gmail.com>
---
Also update some tests; disregard the previous patch.
 Documentation/git-remote.txt |    4 ++--
 builtin-remote.c             |    2 +-
 t/t5503-tagfollow.sh         |    2 +-
 t/t5512-ls-remote.sh         |    2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 2cbd1f7..04de972 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git-remote'
-'git-remote' add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
+'git-remote' add [-t <branch>] [-m <master>] [--no-fetch] [--mirror] <name> <url>
 'git-remote' rm <name>
 'git-remote' show <name>
 'git-remote' prune <name>
@@ -34,7 +34,7 @@ Adds a remote named <name> for the repository at
 <url>.  The command `git fetch <name>` can then be used to create and
 update remote-tracking branches <name>/<branch>.
 +
-With `-f` option, `git fetch <name>` is run immediately after
+Without the `--no-fetch` option, `git fetch <name>` is run immediately after
 the remote information is set up.
 +
 With `-t <branch>` option, instead of the default glob
diff --git a/builtin-remote.c b/builtin-remote.c
index 044215a..c0d7d96 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -54,7 +54,7 @@ static int fetch_remote(const char *name)
 
 static int add(int argc, const char **argv)
 {
-	int fetch = 0, mirror = 0;
+	int fetch = 1, mirror = 0;
 	struct path_list track = { NULL, 0, 0 };
 	const char *master = NULL;
 	struct remote *remote;
diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh
index 86e5b9b..fd075d9 100755
--- a/t/t5503-tagfollow.sh
+++ b/t/t5503-tagfollow.sh
@@ -134,7 +134,7 @@ test_expect_success 'new clone fetch master and tags' '
 		mkdir clone2 &&
 		cd clone2 &&
 		git init &&
-		git remote add origin .. &&
+		git remote add origin .. --no-fetch &&
 		GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U &&
 		test $B = $(git rev-parse --verify origin/master) &&
 		test $S = $(git rev-parse --verify tag2) &&
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index c0dc949..08855ed 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -17,7 +17,7 @@ test_expect_success setup '
 		git show-ref -d	| sed -e "s/ /	/"
 	) >expected.all &&
 
-	git remote add self $(pwd)/.git
+	git remote add self $(pwd)/.git --no-fetch
 
 '
 
-- 
1.5.5.25.g9415
Wincent Colaiuta· Apr 11, 2008, 19:36 UTC · re: Gabriel · lore

Re: [PATCH] Default to fetching a remote after adding it.

El 11/4/2008, a las 21:29, Gabriel escribió:
> This is what the user wants in 99% of cases.
Not sure about that. I often add a remote then push, not fetch.

Cheers, Wincent

Gabriel· Apr 11, 2008, 19:46 UTC · re: Wincent Colaiuta · lore

Re: [PATCH] Default to fetching a remote after adding it.

On Fri, 11 Apr 2008 21:36:27 +0200, Wincent Colaiuta wrote:
> El 11/4/2008, a las 21:29, Gabriel escribió:
>> This is what the user wants in 99% of cases.
> 
> Not sure about that. I often add a remote then push, not fetch.
I didn't see that.
Well, disregard this patch, it was a bad idea to change that default.
Luciano Rocha· Apr 11, 2008, 10:15 UTC · re: Ingo Molnar · lore

Re: git annoyances

Another inconsistency:
$ git remote prune
usage: git remote
   or: git remote add <name> <url>
   or: git remote rm <name>
   or: git remote show <name>
   or: git remote prune <name>
   or: git remote update [group]
show specific options
    -n, --dry-run         dry run
It took me a while to parse the "show specific options" properly.
Wouldn't "specific options for show" be better?
-- 
Luciano Rocha <luciano@eurotux.com>
Eurotux Informática, S.A. <http://www.eurotux.com/>
Wincent Colaiuta· Apr 11, 2008, 10:27 UTC · re: Luciano Rocha · lore

Re: git annoyances

El 11/4/2008, a las 12:15, Luciano Rocha escribió:
Show 16 quoted lines
>
> Another inconsistency:
> $ git remote prune
> usage: git remote
>   or: git remote add <name> <url>
>   or: git remote rm <name>
>   or: git remote show <name>
>   or: git remote prune <name>
>   or: git remote update [group]
>
> show specific options
>    -n, --dry-run         dry run
>
> It took me a while to parse the "show specific options" properly.
>
> Wouldn't "specific options for show" be better?
Yes, or failing that: "show-specific options:"

Without the hyphen "show specific options" reads as "verb adjective noun".

Cheers, Wincent

Jeff King· Apr 10, 2008, 00:33 UTC · lore

Re: Friendly refspecs (Was: Re: git annoyances)

[Your message didn't go to the list, but I think it was supposed to, so I am re-adding the list].

On Thu, Apr 10, 2008 at 01:16:57AM +0200, Sverre Rabbelier wrote:
Show 11 quoted lines
> >  I wonder if people like Linus who do a lot of one-off pulls would find
> >  that too cluttery. I guess we can post a patch and see. ;)
> 
> Maybe a 'newbie' configuration option could be added?
> We can then, if that option is set, provide this kind of information
> to the user.
> Then, later on, when the user is more confident, they can unset the option.
> I reckon it should be set to default-off but that we should provide an
> easy way to turn it on.
> (That is, 'git config newbie on', is easy enough, as long as it is
> mentioned in a/the newbie guide)

This has been discussed before, and I think the general consensus was that it's a bad idea to separate the "newbie" and "expert" experience too much. It makes it harder to provide advice and documentation that works for everyone.

Now that argument generally applies to _behavior_ changes, not verbosity of messages. But in this case, I think it is easy enough to find a "right" behavior for everyone: show the message on fetch, which would otherwise be a very confusing command, but suppress it on "pull", where the fetching is mostly a side effect.

-Peff
Sverre Rabbelier· Apr 10, 2008, 07:58 UTC · re: Jeff King · lore

Re: Friendly refspecs (Was: Re: git annoyances)

On Thu, Apr 10, 2008 at 2:33 AM, Jeff King <peff@peff.net> wrote:
> [Your message didn't go to the list, but I think it was supposed to, so
>  I am re-adding the list].

Yes, it was supposed to go to the list, my bad for hitting 'reply' instead of 'reply to all'.

Show 17 quoted lines
>  On Thu, Apr 10, 2008 at 01:16:57AM +0200, Sverre Rabbelier wrote:
>  > >  I wonder if people like Linus who do a lot of one-off pulls would find
>  > >  that too cluttery. I guess we can post a patch and see. ;)
>  >
>  > Maybe a 'newbie' configuration option could be added?
>  > We can then, if that option is set, provide this kind of information
>  > to the user.
>  > Then, later on, when the user is more confident, they can unset the option.
>  > I reckon it should be set to default-off but that we should provide an
>  > easy way to turn it on.
>  > (That is, 'git config newbie on', is easy enough, as long as it is
>  > mentioned in a/the newbie guide)
>
>  This has been discussed before, and I think the general consensus was
>  that it's a bad idea to separate the "newbie" and "expert" experience
>  too much. It makes it harder to provide advice and documentation that
>  works for everyone.

I would agree here, not only will it make it hard to provide consequent advice and documentation, it will also make it more difficult to switch to "expert" mode if the "newbie" mode is a lot different.

Show 5 quoted lines
>  Now that argument generally applies to _behavior_ changes, not verbosity
>  of messages. But in this case, I think it is easy enough to find a
>  "right" behavior for everyone: show the message on fetch, which would
>  otherwise be a very confusing command, but suppress it on "pull", where
>  the fetching is mostly a side effect.

This makes sense, but I think that if it is made default behavior it would be nice to add a way to make it quiet. Perhaps 'quiet' can be used (I recall seeing used it elsewhere), either through a config option or a command line argument. Then again, if everybody agrees that this added verbosity is good, there'd be no reason to go through that trouble.

Cheers,
Sverre Rabbelier

← back to recent threads