Re: Difficulties in advertising a new branch to git newbies

Previous thread: Re: Why is git clone not checking out files? by Jakub Narebski on Tuesday, January 30, 2007 - 11:15 am. (21 messages)

Next thread: Re: MinGW port usable by Johannes Sixt on Tuesday, January 30, 2007 - 1:20 pm. (1 message)
From: Carl Worth
Date: Tuesday, January 30, 2007 - 1:13 pm

So here's a scenario I'm in right now. A user of my software reported a
bug. I put together some patches to fix the bug and pushed them out as
a new branch "proposed-fix" that I'd like the user to test.

I'm trying to let the user know about the new branch, but I have some
users that know nothing about git. So I'm going to spell things out
fairly carefully, (which I'm glad to do). I also don't know how recent
a version of git the user has, (for example if clone will give
separate remotes or not).

Also, these users are glad to follow instructions, but they're really
interested in just testing the fix I'm offering, and not interested in
getting involved in a git tutorial just yet. (Though, I'd be quite
happy if they found this a gentle and enjoyable introduction to git).

I'm finding that the instructions I'm having to write are much more
complicated than I would like them to be. And some of this is due to
incompatibility between git 1.5 and previous versions. I would be glad
to see improvements to my instructions, (or improvements to git to
allow my instructions to be simpler).

Here's what I've done historically:

	I've published a new "proposed-fix" that I'd like you to
	test. You can obtain this code as follows:

		git clone git://git.project.org/~cworth/project
		cd project
		git checkout -b build proposed-fix

	or alternately, if you've already got a clone of the project
	around, just do:

		git fetch git://git.project.org/~cworth/project proposed-fix:proposed-fix
		git checkout -b build proposed-fix

The things I haven't liked in the above are:

	1. The doubled-up "branch:branch" thing in git-fetch, which
           just plain looks awkward. Yes, it's common for "git pull"
           to fetch something and not store it in any branch, but it
           seems that it could ask for that behavior explicitly and we
           could make "fetch URL branch" act as "fetch URL
           branch:branch".

	2. The "-b build" thing in git-checkout. Worse than just
      ...
From: Matthias Lederhofer
Date: Tuesday, January 30, 2007 - 3:33 pm

How about this:

Create a directory, change into it and run git-init-db.
Get the latest version:
$ git fetch --force URL branch:origin
$ git reset --hard origin
Warning: this will overwrite changes you made to files in the
repository (e.g. the Makefile).

You can also drop the --force if you're sure your branch will always
fast-forward.
-

From: Matthias Lederhofer
Date: Tuesday, January 30, 2007 - 3:36 pm

Reading your original post again: this is not exactly nice but it
should work with any version of git, there shouldn't be many error
conditions and it allows to use the same commands for the initial
checkout and later updates.
-

From: Jeff King
Date: Tuesday, January 30, 2007 - 4:10 pm

I don't see any reason why we can't scare the user when making a commit,
instead of just checkout out to look around. Something like the patch
below. It needs a few things:
  - remove the old checkout message
  - we wrap the colorization over the multi-line message. Probably a
    color_printf_lines() function should be added
  - if colorization is enabled, print it using color.status.warning
    (default to red).

I'm happy to make all those happen if there is interest (Junio, please
comment).

diff --git a/wt-status.c b/wt-status.c
index 5567868..285c824 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -22,6 +22,12 @@ static const char use_add_rm_msg[] =
 "use \"git add/rm <file>...\" to update what will be committed";
 static const char use_add_to_include_msg[] =
 "use \"git add <file>...\" to include in what will be committed";
+static const char detach_warn[] =
+"# Any commits you make may become inaccessible if you checkout\n"
+"# another branch. To save them, you may create a new branch\n"
+"# from the current HEAD using:\n"
+"#   git checkout -b <new_branch_name>\n"
+"#";
 
 static int parse_status_slot(const char *var, int offset)
 {
@@ -303,16 +309,13 @@ void wt_status_print(struct wt_status *s)
 	s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
 
 	if (s->branch) {
-		const char *on_what = "On branch ";
-		const char *branch_name = s->branch;
-		if (!strncmp(branch_name, "refs/heads/", 11))
-			branch_name += 11;
-		else if (!strcmp(branch_name, "HEAD")) {
-			branch_name = "";
-			on_what = "Not currently on any branch.";
+		const char *c = color(WT_STATUS_HEADER);
+		if (!strncmp(s->branch, "refs/heads/", 11))
+			color_printf_ln(c, "# On branch %s", s->branch+11);
+		else {
+			color_printf_ln(c, "# Not currently on any branch.");
+			color_printf_ln(c, detach_warn);
 		}
-		color_printf_ln(color(WT_STATUS_HEADER),
-			"# %s%s", on_what, branch_name);
 	}
 
 	if (s->is_initial) {
-

From: Junio C Hamano
Date: Tuesday, January 30, 2007 - 6:34 pm

That does not protect anything other than interactive "git
commit".  People often do "git commit -m" or "git commit -C".
In addition, rebasing a detached HEAD, merging into a detached
HEAD, cherry-picking onto a detached HEAD or running reset on a
detached HEAD to move to a particular state you want to look at
are all useful and valid operations, and you wouldn't get any
warning when you do so.

I do not think warning at every step that you are "in a funny
state" does not help productivity, so I'd prefer warning upfront
once and be silent afterwards, until you try to come back with
"git checkout <existing branch>", potentially losing your state,
which is what we currently do.

Having said that, I think making "git checkout -f" not to issue
the warning might be enough.  Actually, I would even say it
would make perfect sense.

For situations like Carl's intstruction where a user, who is
purely a sightseer, uses the detached HEAD to go-and-look a
particular state, the fact that "-f" loses the previous local
modifications is not an issue at all.  On the other hand, if the
user is a developer who uses git, the warning upfront (if we
want to keep it for educational purposes, to make people aware
of what is happening) is useful without "-f", and when a user
who is using git to manage his own development, he hopefully
knows what "git checkout -f" means to his local modifications
already.

-

From: Nicolas Pitre
Date: Tuesday, January 30, 2007 - 6:51 pm

I agree entirely.


Nicolas
-

From: Jeff King
Date: Tuesday, January 30, 2007 - 8:22 pm

I'm not even sure what it means to rebase a detached HEAD. Merging

Running reset on a detached HEAD isn't a problem unless you've done one

I didn't quite parse your first sentence, but I think I get the general
meaning. I just think it is awkward to have to either see such a warning
(or use -f) just to _look_ at detached commits, when you aren't doing
anything even remotely dangerous. The dangerous thing is _creating_
commits on top of a detached head.  I honestly don't think it should be
allowed at all, but since some people have argued that it is useful,
that seems like the place to put warnings. Anything else is just making
things more confusing for the sorts of people Carl is dealing with --

Yes, though it would be nicer not to have to explain to them why '-f' is
needed.

-Peff
-

From: Nicolas Pitre
Date: Wednesday, January 31, 2007 - 7:59 am

I disagree again.  Making commits on a detached head is not dangerous.

What is dangerous is moving away from the tip of that detached head 
without attaching it somewhere.  And that case is well covered already.

Also the warning when moving to a detached head is useful to make the 
user aware of what just happened because there is really something 
special about such checkout.  It is not meant to frighten users and if 
it does so then maybe it should be reworked some more.  But IMHO it is 
important that the user be aware of this special state.

But making a warning at commit time is wrong. It is completely 
disconnected from the actual issue and I think it'd create more 
confusion because there is in fact nothing to worry about at the moment 
the commit is made.  The very fact that you think yourself that a 
warning should be displayed at commit time indicates to me that you 
might be a bit confused yourself and such warning if present at commit 

In Carl's case suggesting -f is probably not a good idea.  Using -f _is_ 
dangerous and we better not get people into the habit of using -f 
without thinking.

Let's focus on the real issue: the warning message when head gets 
detached.  This message is not meant to frighten users.  It is meant to 
make the user aware of a special state (pretty useful but special 
nevertheless) and give a suggestion about what to do if that state was 
entered by mistake.  So if that message scares users away then it is the 
message itself which is buggy not its presence.


Nicolas
-

From: Jeff King
Date: Wednesday, January 31, 2007 - 10:07 am

Sure, the dangerous thing is moving away. But my point is there are many
steps leading up to that, and we can warn at any one. However, the
warning is _most_ useful as close to the dangerous thing as possible
(ideally, we would warn when doing the actual dangerous thing, but IIRC,
there was some complexity with that).

IOW, here's a rough flow chart of states and user actions:
         checkout non-branch          commit, etc
(1) regular  ---------> (2) detached,  --------> (3) detached,
         ^                  no commits                commits
         |  checkout branch |  checkout old branch     /\
          \-----------------<--------------------------  |
                                                         |  checkout
                                                         | new branch
                                                         v
                                                   (4) new regular branch

Hopefully my ASCII art skillz are coherent enough. The actual
"dangerous" thing here is moving from 3 to 1. We can theoretically warn
at any transition. Right now we warn moving from 1 to 2. But a large
number of users are just going to go right back to 1, never even doing
anything dangerous! For them, the warning is confusing. I'm proposing
warning between 2 and 3. I would also be happy with warning (and
probably blocking without -f) moving from 3 to 1, which is the actual
dangerous thing. However, I think putting a warning between 2 and 3 is
reasonable, because the next step the user will make from 3 is either
moving to 1 (dangerous) or to 4 (ok), and they must use the correct
git-checkout invocation. So basically, it's our last chance (besides the

What is so special about it? My argument is that it is not really very
special _until you make commits_. Are there other operations which we

I think you are proving my point here. If you think warning at commit
time is too early, then how is warning _before_ that (when we detach)


Again, I don't ...
From: Nicolas Pitre
Date: Wednesday, January 31, 2007 - 11:59 am

The _only_ dangerous thing is moving away.  Warning at any step is far 
more annoying than warning (actually only notifying) only once when the 

Let's fix the warning then.  But it must stay just because it is 
important that the user know _why_ and _when_ the head became detached.  
Realizing that head is detached later is far more confusing if the user 

Given that the commit template already says that the head is detached is 


No it is not.  The user cannot escape the detached head state (moving 
from 3 to 1) without -f or creating a new branch already.  Additional 
warning between (2) and (3) does nothing but add annoyance to the user 

It is a different state and the user must know why.  When doing a commit 

Did I say anything about it being too early?

I say that it is unnecessary and redundent, and that it would create 

It is special because it has an entry point and an exit point, unlike 
being on any branch where there is no such notion.  So it is important 
to know when/how you enters it and how you may leave it.  Intermediate 
operations don't have to be special with useless warnings.


Nicolas
-

From: Jeff King
Date: Wednesday, January 31, 2007 - 3:53 pm

Doh! I'm a complete moron. Sorry, but I thought we were _not_ warning
there in favor of the warning at time of detachment. I even did a test,
but I botched it.

So please, accept my apology and assume I have hit myself over the head
with the clue stick several times. Warning at commit time _is_ stupid,

OK, I completely see your point now; it doesn't have to be a _warning_
per se, but rather to let the user know this is when the state changed

You said "...there is in fact nothing to worry about at the moment the
commit is made." My point is that there is in fact nothing to worry
about at the moment that you detach, thus why should one get a warning
and not the other. But I agree that if you want the later warning to
make sense, it might be helpful to note that point (and I think it's
getting too fancy to tuck away that information and have the actual
warning say "When you moved your HEAD to foo~32, you were no longer on a
branch, therefore...")

So IOW, I think I agree with you now. :)

Again, sorry for the (my) confusion.

-Peff
-

From: Nicolas Pitre
Date: Tuesday, January 30, 2007 - 6:48 pm

Note that the latest revision on the master branch of git has a slightly 

I don't think that is a good idea in general.

It is already kind of a challenge to teach people about git's branch 
concept.  The detached head is yet another exotic thing about git that 
is sure not to be really obvious to everyone.  Now if you remove the 
message to hide the detached head state from the user just to come later 
on with a "hey btw did you know that your head was detached?" message 
then you can be assured that most people will simply go WTF.


Nicolas
-

From: Daniel Barkalow
Date: Tuesday, January 30, 2007 - 5:10 pm

I think the warning should just be something where a user following your 
instructions will say, "ah, yes, that's actually what I want." Maybe:

  warning: you are now browsing the history without a local branch. You 
  will not be able to commit changes unless you create a new local branch 
  with "git checkout -b <new_branch_name>".

It's a bit silly for us to simply warn people that they're using this 
feature, rather than telling them what the potential downside is. Since 
it's marked as a warning, with no further information, the intuitive 
inference is that all sorts of bad things could happen (like, too many for 
us to list). At least we don't say "warning: your HEAD is now detatched" 
but still...

	-Daniel
*This .sig left intentionally blank*
-

From: Nicolas Pitre
Date: Tuesday, January 30, 2007 - 6:55 pm

This isn't true.  You can commit on top of a detached head.  In fact you 
can do almost anything.


Nicolas
-

From: Daniel Barkalow
Date: Tuesday, January 30, 2007 - 10:09 pm

"Commits you make will not be attached to permanent state unless you 
create a local branch"? I'm not sure how the feature turned out to work, 
but I know that (a) you're fine if you don't make any commits and (b) the 
behavior is more like what happens with anonymous checkouts of other 
people's repositories in non-distributed SCMs, so people will tend to
underestimate what they can do with this, rather than overestimating it 
and getting into trouble.

I suppose it's reasonable to warn at commit time, if we ended up going 
with allowing commits like normal.

	-Daniel
*This .sig left intentionally blank*
-

From: Nicolas Pitre
Date: Wednesday, January 31, 2007 - 7:31 am

I disagree.

It is not the commit which is dangerous when the head is detached.  It 
is the checkout of another branch.  And this case is covered already 
such that the checkout is refused unless you actually create a branch 
for your detached head or you give -f to checkout to override the 
protection.

Giving a warning at commit time is not the place where the user has to 
be aware of the issue since it is indeed not the place where there is 
any issue to worry about.


Nicolas
-

From: J. Bruce Fields
Date: Wednesday, January 31, 2007 - 7:38 am

By the same argument, the original checkout of a non-branch is also not
the place for a warning; by the time you commit and then do a checkout
to switch away from the new commit, that original checkout may be a
distant memory.

--b.
-

From: Daniel Barkalow
Date: Wednesday, January 31, 2007 - 9:25 am

At commit time, the user is reasonably likely to be doing something 
unintended (at least, it's more likely that the user is doing something 
unintended by committing with a detatched head than that the user is doing 
something unintended by detatching the head). Certainly the only time 
there's any danger of losing work is when the head is detatched and a 
commit has been made since it was set, because otherwise there's either no 
work to lose, or no commits could be becoming unreachable.

I suspect that there will be people from other SCMs who will assume 
they're back on a local branch if the system lets them commit, because 
they would be prohibited from committing on top of an anonymous checkout 
or a historical commit. Of course, they can cherry-pick the misplaced 
commit, so it's not a big deal, but I think it's where a naive user would 
be getting into a state they don't understand.

	-Daniel
*This .sig left intentionally blank*
-

From: Nicolas Pitre
Date: Wednesday, January 31, 2007 - 11:25 am

There is protection against losing a commit made on top of a detached 
head already.  And when reflog of detached head can be completed then 
there won't be any ways to lose them regardless.  Preventing or making 
it difficult or annoying to commit on top of a detached head 1) makes no 

I don't follow you here.

Why would you be prevented from performing a commit on top of an 
historical commit?  That is the whole point of a detached head: making 
things to a checkout that usually should remain read-only.  This is why 
you can fetch and merge tracking branches, diff against taged commits or 
tracking branches, etc.  But if you _checkout_ a read-only branch/tag 
then either we checkout every file read-only to inforce that face and 
piss off users, or let them do as much as they wish _including_ commits 
but have a safety gate for the only operation that could otherwise 
actualy lose work.

And since the commit template already mention "Not currently on any 
branch" I think the user is reminded already that she's still not on a 

That's why the warning when detaching head is important:

|warning: you are not on ANY branch anymore.
|If you meant to create a new branch from this checkout, you may still do
|so (now or later) by using -b with the checkout command again.  Example:
|  git checkout -b <new_branch_name>

The "now or later" is there exactly to tone down the warning.  And 
actually we could do s/warning/note" to make it even less frightening.  

But I think it is important to tell the user up front about that fact. 
Then, when the user tries to commit and sees "Not currently on any 
branch" then she'll go "oh sure it told me so before" and maybe even 
"that's so cool I can perform commits even in this case!".  But if the 
user sees that "Not currently on any branch" line without having been 
notified at the moment it happened then she'll only think "WTF did I do 
to get here".

But if a user did work, even unexpectedly, on top of a detached head 
then the worst ...
From: Guilhem Bonnefille
Date: Wednesday, January 31, 2007 - 6:13 am

If the user is not a developer and only interested in testing, what
about a simple snapshot tarball?
So, you prepare the fix and then you pack everything in a
myapp-timestamp.tar.gz and send this tarball to the user.

-- 
Guilhem BONNEFILLE
-=- #UIN: 15146515 JID: guyou@im.apinc.org MSN: guilhem_bonnefille@hotmail.com
-=- mailto:guilhem.bonnefille@gmail.com
-=- http://nathguil.free.fr/
-

From: Carl Worth
Date: Wednesday, January 31, 2007 - 9:06 am

That's bad for all the same reasons we don't send tarballs around to
each other.

But here are several concrete points:

1. I want to be able to easily publicize a new branch with
   instructions that anyone can use, (regardless of git experience).

2. I've got the stuff available in a git branch already, and I don't
   want to do any more work.

3. I want the exchange to be as efficient as possible, (I might send
   multiple fixes in series to the user and it'd be really nice to
   take advantage of git's efficiency here).

4. I don't want to condemn the user to never being able to learn
   git. If I make this easy for the user then I get a nice lead-in to
   teach the user new things, (which is good for me since it helps me
   if the user starts sending me git commits rather than random
   patches without commit messages connected to who-knows-what
   tar-file version of the software, etc.)

etc. etc.

-Carl

PS. All that being said, our project does publish periodic tar-file
snapshots. But that's really for a different situation: specifically,
for people with whom I'm not already engaged in any conversation at
all.
From: Johannes Schindelin
Date: Wednesday, January 31, 2007 - 9:15 am

Hi,



How about gitweb, with a snapshot link? It's as easy as it gets. Even 
those Windows idio^H^H^H^Husers can unpack tar.gz files by now, and you 
send them just a link. They can even see what was fixed, and when, if they 

That is one of the lousiest excuses in this world. Unfortunately, I hear 

There's two kinds of efficient here. Efficient in the sense of network 
traffic, or in the sense of time spent talking back and forth, until the 
package is finally tested.

If the efficiency you are thriving for is network traffic, go a head, make 
the user use git.

However, if it is the other efficiency you want to achieve, stay away from 
git. Chances are that your user will never appreciate what git can to for 
her, and just wants to test the darned package, and be done with it, 

That's nice of you. But it might just be that you royally p*ss the 
customer off, because he does not have time for that game.

Ciao,
Dscho

-

From: sbejar
Date: Wednesday, January 31, 2007 - 12:27 pm

Actually it is the same "problem" as when you want to work on the
non-HEAD remote branch.

Currently I do (with current git):

git clone git://...
git checkout -b ${branch} origin/${branch}
git config branch.${branch}.merge refs/heads/${branch}

then they could update this with just:

git pull

It would be nice if:

git clone -b ${branch} git://...

would be equivalent of the above three commands.

Santi
-

From: Carl Worth
Date: Wednesday, January 31, 2007 - 12:50 pm

Yes, something like that would be extremely helpful!

In addition, it would be great to have a command that did the same
setup within an existing repository.

And I would be most happy if the two commands for these two use cases
shared as much syntax as possible, so I could publish one string and
users could cut-and-paste it to either command as appropriate.

One string I would have liked would have been "git://... ${branch}",
but existing git-clone and git-fetch command syntax is not too
amenable for that, (git-clone interprets an argument after the URL as
the name of the local directory to create while git-fetch interprets
the argument after the URL as a refspec).

-Carl
From: Josef Weidendorfer
Date: Wednesday, January 31, 2007 - 5:20 pm

Nice indeed.

Additionally, it would be nice for clone to directly
checkout tags. Why not an option "--checkout <ref>"
to directly checkout <ref> after cloning?

This goes nicely with the "-b" option
to create a new branch. A "-b <branch>" option alone would
imply "--checkout origin/<branch>". And without "--checkout"
or "-b" option it defaults to "-b master" which gives
exactly the same behavior as now.

This way,

 git clone --checkout v1.0 git://...


Why not use "git clone" for this?
Currently, the man page says about the directory it will clone into:

 "Cloning into an existing directory is not allowed."

But we could relax this: if the specified directory is the root of
a checkout (ie. with a .git subdir), we would clone a remote repository
into the same local repository. However, this should not default
to "-b master", ie. not switch the current branch. Additionally, the
remote name should not default to "origin", but to the 
"humanish" part of the source repository. IMHO we should have done
the latter since long time ago, as a remote "origin" is not really
useful once you work with branches from multiple remote repositories.

Doing this,

 git clone git://... <newdir>

would be the equivalent of

 mkdir <newdir>
 cd <newdir>
 git init
 git clone -b master git://... .


You would say:

"To get version <xyz>, do a

  git clone --checkout <xyz> git://...

If you already have a local clone of the repository, append the
directory of your local repository as target to clone this version

IMHO "-b" option is better as it tells you that it creates a new
local development branch for you.



-

From: sbejar
Date: Thursday, February 1, 2007 - 2:02 am

You can do it with git-remote. I think it is sensible to have a
command to get a new repository and a command to have a new remote.

For the "work on the non-HEAD branch" I think we could have:

# clone a remote repository and start working with branch ${branch}
$ git clone -b ${branch} ${url}

# add a new branch based on a remote branch,
# and configure to pull from there.
$ git branch ${branch} ${remote_branch}
$ git checkout -b ${branch} ${remote_branch}

as you see it is the current syntax, so I suggest to automatically
setup the branch.${branch}.{remote,merge} configs to follow the
${remote_branch} if this is sensible. So for example

$ git clone ${url_of_git.git}
$ cd git
$ git checkout -b maint origin/maint
$ git-config -l | grep ^branch.maint
branch.master.remote=origin
branch.master.merge=refs/heads/maint

( or branch.master.merge=refs/remotes/origin/maint )

This changes the current behaviour, but I think it make sense. If this
is not possible another way would be to have another option (-r for
remote, or -f for follow, or -p for pull, or -m for merge, ...) as:

$ git branch ${branch} -r ${remote_branch}
$ git checkout -b ${branch} -r ${remote_branch}

And if you want to add/change the remote/merge config for an existing
branch, in addition to doing this with git-config, git-remote could do
it as it currently shows the tracking branches.

Santi
-

From: Carl Worth
Date: Monday, February 5, 2007 - 10:51 pm

When I first brought up this thread we had lots of good discussion
about detached head that led to improved (or eliminated) warning
messages, and some good motivation for HEAD reflog.

Meanwhile, there's still a piece of the original problem that was not

Is there any feedback on the above? I just ran into this problem again
tonight, giving out instructions of "git checkout -b build
proposed-fix" and then bracing myself to have the user complain about
an error of:

	git checkout: updating paths is incompatible with switching branches/forcing
	Did you intend to checkout 'proposed-fix' which can not be resolved as commit?

To which I'd have to respond, "Oh, you're using a newer git. In your
case use 'git checkout -b build origin/proposed-fix'".

So, could we fix this so that a remote branch name will resolve
without the "origin/" prefix if it is not ambiguous?

I can imagine the resolution rules are already fairly complicated, (I
don't even know what they all are already). But when there is no
ambiguity, and when the behavior would be backwards compatible to git
before separate-remotes, is there any reason this would be a bad idea?

Thanks,

-Carl
From: Junio C Hamano
Date: Monday, February 5, 2007 - 11:37 pm

I am fairly negative on this one, especially I do not think the
symptom deserves to be described with the word "fix".  DWIM is
good, but it has bounds, and this particular one feels it is
slightly on the other side of the boundary.  We currently only
DWIM out of a fixed set of patterns -- if you want to extend it,

If you add another DWIM rule, then I suspect that you would have
harder time explaining why they get "hey, that is ambiguous"
error.


-

From: Junio C Hamano
Date: Tuesday, February 6, 2007 - 12:25 am

One of the reasons I do not think it is a good idea is, saying
"if unique" makes it sound as if it is sane, but it forgets that
what confusion it is bringing into the picture when not unique.

If somebody says "git show master", obviously it would be found
under refs/heads/, and most likely there would be a tracking
branch refs/remotes/origin/master if you are not the project
lead, and if you work on more than one machines using
mothership-satellites configuration, you would probably have
refs/remotes/note/master and refs/remotes/laptop/master on your
mothership machine.  Now, "master" is not unique, but I do not
think we would want to complain "Gaah, master is not unique!  If
you mean heads/master, say so".

So addition to "if unique", we need another DWIM rule that says
"refs/heads/branch" trumps even when there are branch elsewhere
and prevents ambiguity rule from triggering.

And that is only one example I can think of in 10 minutes while
watching TV sitting next to my wife, without thinking much about
git X-<.  Who knows what other additional confusion we are
talking about?  That is what I fear most.


-

From: Jeff King
Date: Tuesday, February 6, 2007 - 12:31 am

FWIW, the patch I just posted allows all existing lookups to trump
refs/remotes/*/%s, but will complain of ambiguities between remotes.
But please don't take my patch as a vote for this being sane. :) I just
wanted to give Carl something to play with.

-Peff
-

From: Carl Worth
Date: Tuesday, February 6, 2007 - 11:53 am

I can accept that argument.

With "fix" I was referring to the backwards-compatibility problem,
(that I don't have a way to give branch checkout instructions to users
that will work for both 1.5 and pre-1.5 versions of git). As is, if
I provide instructions that don't match the version the user has, then
the user will see a rather confusing message:

	git checkout: updating paths is incompatible with switching branches/forcing
	Did you intend to checkout 'origin/8801' which can not be resolved as commit?

[And perhaps the message above is evidence for too much DWIM in the
interface already---that checkout will accept either a revision
specifier or a path name and do fairly distinct operations depending
on which it gets.]

If my tail-matching-for-remotes idea won't fly, are there any other
suggestions for a way to provide instructions for this step that would

Well, ideally git would explain the ambiguity with something like
this:

	There are multiple "proposed-fix" remote-tracking
	branches. Please specify which you would like:

		origin/proposed-fix
		something-else/proposed-fix

And I would think that this would not even be surprising since the
user would not get into this situation by default, but would actually
have to have added an additional something-else remote before being
able to get this kind of ambiguity.

But, like I said, I'm glad to accept that the tail-matching idea is a
bad idea. Feel free to drop that on the floor. I'm more interested in
the compatibility issue.

-Carl
From: Junio C Hamano
Date: Tuesday, February 6, 2007 - 12:14 pm

If you tell your users to --use-separate-remote in the "git
clone" instruction, would that solve your backward compatibility
problem?

-

From: Carl Worth
Date: Tuesday, February 6, 2007 - 12:39 pm

Ah, yes. That should actually do the trick.

Thanks,

-Carl
From: Jeff King
Date: Tuesday, February 6, 2007 - 12:28 am

I'm not convinced that the complication is a good idea.  However, if you
would like to play with it, a patch is below (it depends on my 'add
utility functions for enumerating remotes' patch, which I just posted).

-- >8 --
sha1_name: match refs in 'refs/remotes/*/%s'

If no other matches are found for a ref, then look for it in every defined
remote. This will not complain of ambiguity, since we only do the lookup if
no other ref matches.
---
 sha1_name.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index d77f770..d9fe107 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -5,6 +5,7 @@
 #include "blob.h"
 #include "tree-walk.h"
 #include "refs.h"
+#include "remotes.h"
 
 static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
 {
@@ -235,6 +236,30 @@ static int ambiguous_path(const char *path, int len)
 	return slash;
 }
 
+struct match_ref_in_remote_data {
+	const char *ref;
+	int ref_len;
+	int count;
+	unsigned char *sha1;
+	char *resolved;
+};
+static int match_ref_in_remote(const char *remote, void *data)
+{
+	struct match_ref_in_remote_data *md = data;
+	unsigned char sha1_from_ref[20];
+	const char *r;
+
+	r = resolve_ref(
+		mkpath("refs/remotes/%s/%.*s", remote, md->ref_len, md->ref),
+		md->count ? sha1_from_ref : md->sha1,
+		1, NULL);
+	if (r) {
+		if (!md->count++)
+			md->resolved = xstrdup(r);
+	}
+	return 0;
+}
+
 static const char *ref_fmt[] = {
 	"%.*s",
 	"refs/%.*s",
@@ -264,6 +289,18 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 				break;
 		}
 	}
+
+	if (!refs_found) {
+		struct match_ref_in_remote_data md;
+		md.ref = str;
+		md.ref_len = len;
+		md.count = 0;
+		md.sha1 = sha1;
+		for_each_remote(match_ref_in_remote, &md);
+		refs_found = md.count;
+		*ref = md.resolved;
+	}
+
 	return refs_found;
 }
 
-- 
1.5.0.rc3.554.ga40e-dirty

-

From: Junio C Hamano
Date: Tuesday, February 6, 2007 - 12:46 am

I think the abstraction is wrong -- why do you even need to
iterate over .git/remotes (and .git/config remote.*) when the
only thing this cares about is refs under refs/remotes/*
hierarchy?

Or am I missing something blatantly obvious?

-

From: Jeff King
Date: Tuesday, February 6, 2007 - 1:12 am

Well, you obviously can't look in the directory because of packed refs.
You can enumerate all refs with for_each_remote_ref and try to match
against "refs/remotes/*/$ref". But how do you handle '/' in a remote
name or a branch name?  If I have a remote "foo/bar" with branch "baz",
should I match it while looking up "bar/baz"? What about having the
remote "foo" and the branch "bar/baz"? Should a lookup for "baz" find
that?

If I'm just given the collapsed "remote/branch" text, I don't know which
parts are remote and which parts are branch, unless I make the
assumption that remotes have no '/' in them (which I did not think we
were making).

-Peff
-

From: Nicolas Pitre
Date: Tuesday, February 6, 2007 - 8:33 am

Your patch forgot to add the equivalent handling to dwim_log().


Nicolas
-

Previous thread: Re: Why is git clone not checking out files? by Jakub Narebski on Tuesday, January 30, 2007 - 11:15 am. (21 messages)

Next thread: Re: MinGW port usable by Johannes Sixt on Tuesday, January 30, 2007 - 1:20 pm. (1 message)