Re: Cleaning up git user-interface warts

Previous thread: Re: Cleaning up git user-interface warts by Jakub Narebski on Tuesday, November 14, 2006 - 2:01 pm. (4 messages)

Next thread: git-svn and rebase causes duplicate log entries in svn by Joakim Tjernlund on Tuesday, November 14, 2006 - 2:49 pm. (3 messages)
From: Jakub Narebski
Date: Tuesday, November 14, 2006 - 2:30 pm

The git interface refactoring should be I think the cause for git 2.0.0
release...

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git


-

From: Nicolas Pitre
Date: Tuesday, November 14, 2006 - 2:34 pm

Good idea indeed.


Nicolas
-

From: Junio C Hamano
Date: Tuesday, November 14, 2006 - 3:56 pm

We need to avoid user confusion, so making a command that used
to do one thing to suddenly do something completely different is
a no-no.  However, I do not think it needs to wait for 2.0.0.
We can start with a separate namespace (or even a separate
"Improved git UI project") and introduce the "improved UI set"
in 1.5.0 timeframe.

If managed properly, the "improved git UI" can coexist with the
current set of tools and over time we can give an option not to
even install the older Porcelain-ish commands.

-

From: Nicolas Pitre
Date: Tuesday, November 14, 2006 - 6:48 pm

Dunno.  I feel this is a bit overboard.  Actually the naming problem is 
rather localized to one command, namely git-pull.  In my opinion going 
with yet another namespace which would rather add to the confusion not 
clear it.

The best way to avoid user confusion is to remove the source of the 
confusion not let it live.  In other words I think we should _fix_ 
git-pull instead of replacing it.  People are already confused about it 
so simply fixing this command will have a net confusion reduction.  Yet 
we're not talking about "suddenly doing something completely different" 
either.  If git-pull doesn't merge automatically anymore it is easy to 
tell people to use git-merge after a pull.

"You pull the remote changes with 'git-pull upstream,, then you can 
merge them in your current branch with 'git-merge upstream'."

Isn't it much simpler to understand (and to teach) that way?

Also I don't think using git-upload and git-download is much better.  
This adds yet more commands that do almost the same as existing ones but 
with a different name which is yet not necessarily fully adequate.  I 
for example would think that "download" is more like git-clone than 
git-fetch or git-pull.

Let's face it: HG got it right with pull and push and newbies have much 
less difficulty grokking it.  We screwed it by not using the most 
intuitive semantic of a pull and locking the word "pull" away is not the 
better solution given all considerations. Why just not admit it and 
avoid being different than HG just for the sake of it?


Nicolas
-

From: Junio C Hamano
Date: Tuesday, November 14, 2006 - 7:10 pm

If it were "you download the remote changes with 'git download
upstream' and then merge with 'git merge'", then perhaps, but if
you used the word "pull" or "fetch", I do not think so.

I would be all for changing the semantics of "pull" from one
thing to another, if the new semantics were (1) what everybody
welcomed, (2) what "pull" traditionally meant everywhere else.
In that case, we have been misusing it to be confusing to
outsiders and I agree it makes a lot of sense to remove the
source of confusion.  But I do not think CVS nor SVN ever used
the term, and I was told that BK was what introduced the term,
and the word meant something different from what you are
proposing.

You have to admit both pull and fetch have been contaminated
with loaded meanings from different backgrounds. I was talking
about killing the source of confusion in the longer term by
removing fetch/pull/push, so we are still on the same page.

That's where my "you download from the upstream and merge" comes
from.


-

From: Michael K. Edwards
Date: Tuesday, November 14, 2006 - 7:27 pm

I would kind of like to see "git poll" -- visit all remote branches,
fetching objects and tags into the local repository, so that I can
inspect changes off-line and merge, cherry-pick, etc. to my heart's
content.  That would fit the platform integrator's workflow nicely --
"git poll" into a tracking tree, do some merges there (such as
backporting a subsystem to a "stable" base kernel), then merge this
backport branch to each platform working copy and cherry-pick other
changes as necessary.

Cheers,
- Michael
-

From: Nicolas Pitre
Date: Tuesday, November 14, 2006 - 9:20 pm

But the fact is that HG (which has a growing crowd of happy campers, 
maybe even larger than the BK crowd now) did work with and got used to a 
sensible definition of what a "pull" is.  This means that their 
definition is becoming rather more relevant with time than what it used 
to, and because it is a saner definition than what GIT has for the same 
word which HG users really have no issue with, I think we really should 
leverage the "common wisdom" and consider aligning ourselves with them 
in this case rather than trying to go into a totally different 
direction.  We simply won't gain anything trying to teach people "a pull 
in HG is a download in GIT".  If a pull becomes the same thing for both 
then it's one less oddball in the GIT interface.


Nicolas
-

From: Junio C Hamano
Date: Tuesday, November 14, 2006 - 9:58 pm

I personally do not have any issue with that, as long as you
would help us convert existing users that what was known as pull
is not available and new pull means fetching only.

If I recall correctly in this thread, you also advocated to
always have tracking branches.  I am a bit worried about losing
the promiscuous pull usage, which can easily become a regression
for people like Linus in the integrator role unless done with an
escape hatch.

-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 11:03 am

Guys, before you start thinking this way, the fact is, there's a lot of 
happy git users. 

So the reason for using "git pull" is

 - bk did it that way, and like it or not, bk was the first usable 
   distributed system. hg is totally uninteresting.

 - git itself has now done it that way for the last 18 months, and the 
   fact is, the people _complaining_ are a small subset of the people who 
   actually use git on a daily basis and don't complain.

So don't fall for the classic "second system syndrome". The classic reason 
for getting the second system wrong is because you focus on the issues 
people complain about, and not on the issues that work well (because the 
issues that work fine are obviously not getting a lot of attention).

If you think "pull" is confusing, I can guarantee you that _changing_ the 
name is a hell of a lot more confusing. In fact, I think a lot of the 
confusion comes from cogito, not from git - the fact that cogito used 
different names and different syntax was a mistake, I think.

And that '#' for branch naming in particular was (and is) total 
braindamage. The native git branch naming convention is just fundamentally 
much better, and allows you to very naturally fetch multiple branches at 
once, in a way that cogito's syntax does not.

So when I see suggestions of using that brain-damaged cogito syntax as an 
"improvement", I know for a fact that somebody hasn't thought things 
through, and only thinks it's a better syntax beause of totally bogus 
reasons.

I do agree that we probably could/should re-use the "git merge" name. The 
current "git merge" is an esoteric internal routine, and I doubt a lot of 
people use it as-is. I don't think it would be a mistake to make "git 
merge" basically be an alias for "git pull", for example, and I doubt many 
people would really even notice.

But the fact is, git isn't really that hard to work out, and the commands 
aren't that complicated. There's no reason to rename them. We do have 
other ...
From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 11:43 am

Those arguments are somewhat flawed.  If we stick to "BK did it that way 
and it was first", then following that logic we would also carry a lot 
of CVS baggage because "CVS did it that way, and it was the most 
successful of its kind".  Still, we decided not to follow CVS nor BK in 
many ways already.

As for the fraction of people complaining being a small fraction of 
current GIT users: that is easily explainable by the fact that most 
people who would have grown the complainers group are simply not GIT 
users anymore since they were turned away by GIT's current user 
interface issues.  The only complainers remaining are those who see 
value in the GIT technology but who would like to bring more 
intuitiveness to the GIT interface instead of going for the alternative 

The counter part of that is the possibility to fall for the "ivory tower 
syndrome" where seasoned GIT users feel they are well satisfied with 
what is currently available and unwilling to consider changes that would 
reduce the barrier to entry for new users... simply because they are so 
used to the way things work that they can't see why others have problems 

Agreed.  This is why the current discussion led to a proposition that 
allows for "pull" to remain as is but to have a "get" version that would 

Do you have comments on my proposed syntax (that would be implemented 


I agree with you in general, except for the "pull" behavior which is 
really really odd.  Maybe it made sense in the BK context, maybe it is 

Agreed again.


Nicolas
-

From: Shawn Pearce
Date: Wednesday, November 15, 2006 - 11:49 am

Or they are by proxy.

*I* don't see that much of a problem with git pull; I can use it
without trouble at this point.  But I find it difficult to teach
to others.

My complaints about git pull/fetch/push are by proxy for about 10
other users who aren't on the mailing list but whom I interact with
through Git.  They don't like pull/fetch/push very much.

So count my complaints 10 times.  :)

Ok, that's still a drop in the bucket of current Git users.
But still, I'm sure there are others.  I think Carl was recently
talking about complaints from some Fedora folks...

-- 
Shawn.
-

From: Marko Macek
Date: Wednesday, November 15, 2006 - 12:05 pm

Agreed. Personally, the first thing that I notice when trying to switch
 from Subversion to git is the behavior of 'index', mainly in git-diff, git-status and 
git-commit.

For people switching from CVS and SVN it would be much better if the index was hidden 
behind the scenes by using different defaults:

git-commit -a
git-status -a
git-diff HEAD

BTW, currently there's a minor bug: git-diff HEAD doesn't work before you 
make the first commit. Perhaps this should be special cased.

I could personally get used to this, but I'd surely get blank 
stares from people when teaching them the difference.

I guess this is the reason that the GIT Tutorial for CVS/SVN users is talking about _cogito_ instead.
(which is very confusing for someone coming to _git_ home page, trying to learn git).

Mark
-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 1:41 pm

That's only a _bug_ in your implementation of the synonym for
"svn diff" which blindly used "git diff HEAD".

"git diff HEAD" is not a synonym for "svn diff" when HEAD does
not exist yet, because you are asking "please give me a diff
between the tree in the HEAD commit and my working tree files
through the index".  So if you are doing "git-svnish-diff"
Porcelain script, it should notice that HEAD does not exist yet
and take an appropriate action.  We do something similar in
git-status; the porcelain notices and acts differently when HEAD
is not there yet.

This "there is no HEAD yet" is not related to the index, but I
am skeptical about trying to hide the index from the end user.

You can make some things map more naturally to systems like SVN
and CVS than other things.  For example, Nico's proposal to
always use remote tracking branches and defaulting to use
refs/remotes/ would be a way to match UI of pull/push to another
existing system and that would work well (I am not agreeing to
the change to make 'pull' not to do the merge which would break
existing users -- I am just saying that the result would be self
consistent).  But things that have difference at the concept
level, I suspect no clever mapping to hide the differences would
work well.

The index is quite central to the way git works at the concept
level, and I think it is doing disservice to the end user to try
hiding it forever from them and failing to do so, rather than
being honest and teaching them the concept upfront.

But me thinking so does not necessarily mean you are forbidden
from trying.  Your efforts may result in a system where the
index is totally invisible and the end user never has to know
about it.

-

From: Shawn Pearce
Date: Wednesday, November 15, 2006 - 3:07 pm

I agree with what you are saying about the index.

But in git-gui I found myself writing code on Monday which tries to
hide the index from the user unless he/she requested that the index
be made visible.

The reason is there are some users who I'd like to give git-gui to
who I'm not sure I trust to make sure their index is in sync with
their working directory before they commit.  In some cases I'm lucky
that the user even knows what directory their file is stored in.  :-(
Yes, there really are computer users who are afraid of directories
and command lines.

I probably could try to teach them to make sure the final file
is included in the index before committing, but I think that for
most of them they would find this to be just another couple of
mouse clicks they have to perform before every commit, meaning its
something that the #$@!*@!*@$# tool should just do for them.

-- 
Shawn.
-

From: Marko Macek
Date: Wednesday, November 15, 2006 - 11:07 pm

My "implementation" is taken from git-diff man page. It seems obvious
that the situation before the first commit is just a special case if 

I agree, this is a separate issue.

Mark
-

From: Sean
Date: Wednesday, November 15, 2006 - 3:28 pm

On Wed, 15 Nov 2006 20:05:27 +0100

IMHO this is really bad.  Pasky runs the Git web site and feels
that Cogito comes hand in hand with Git.  When I asked him about
it he mentioned that Junio had approved.  But it's very confusing
to click a link that purports to show you how to use Git and get
shown a bunch of Cogito stuff.

Git is confusing enough for new users without "Git" and "Cogito"
being mixed without comment on the Git webpage.  At the very
least, the links should be changed to "Cogito for CVS/SVN users".

Sean
-

From: Andy Parkins
Date: Wednesday, November 15, 2006 - 11:58 am

I'm a happy user, doesn't mean I wouldn't like changes.  In fact, by that 
argument, that there are happy users means that there is no need to ever make 

That's awfully like the argument I hear off my bank whenever I complain to 
them too - "well lots of other people don't complain so we must be right".  
The people who complain are a subset of the people who have complaints.  I 
don't think never changing is a good argument - leaving aside the actual 
changes under discussion - in another 18 months lets say there are double the 
number of git users, and 18 months after that double again - in that case the 

On the one hand you're arguing that git syntax is easy to learn, and on the 


I don't think so.  Mainly because the proposed new git pull would be a subset 
of the existing git pull.  It's not changing function, it's just reducing in 
function.


Andy
-- 
Dr Andrew Parkins, M Eng (Hons), AMIEE
andyparkins@gmail.com
-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 12:18 pm

I'm saying that people who are new to git will _have_ to learn new 
concepts ANYWAY.

I don't think the naming is the hard part. 

The fact is, git is one of the very few (essentially _only_) SCM's that 
make it very clear that all real operations are local and that if you want 
to work with other repositories, you have to "fetch" those into local 
branches first. The fact that "pull" exists at all is really just 
shorthand.

If people have trouble explaining this to others, and have trouble 
grasping "pull", then I will bet that the _real_ issue has nothing at all 
to do with naming at all, and the real issue is that people are being 
_taught_ the concepts in the wrong order.

Before you learn "pull", you should learn "fetch". Don't even _mention_ 
"pull" until the person got what "fetch" means. Because the fact is, 
"fetch" is really the much more fundamental operation, and once you 
really understand what "fetch" does, "pull" is obvious.

So I'll argue that the problem isn't naming, the "problem" is really that 
git has a few fundamnetal concepts that people aren't used to. The most 
fundamnetal of those is the notion of the local branch-space. EVERY other 
(broken) SCM has branches as being some kind of totally idiotic separate 
subdirectories, or doesn't really support branches at all (ie neither BK 
nor CVS really support "branches" - even if a concept of that name exists 
in CVS, it has nothing at all in common with the git model of branches).

But once you understand branches, and understand "fetch" (and it really 
isn't _that_ complicated: fetch really does exactly what the name says, so 
if you understand local branches, you will understand "fetch"), then it's 
a much smaller step to explain "pull = fetch + merge".

But I bet people don't teach it that way. They _start_ by teaching "pull". 
Right?

				Linus
-

From: Michael K. Edwards
Date: Wednesday, November 15, 2006 - 12:39 pm

"git fetch" is certainly the right thing for the platform integration
role, in which one is trying to maintain a series of integration
branches which track the bleeding edge of some subsystems while
keeping the core stable on each branch.  This is not as impossible as
people make it out to be, but there certainly isn't much place for
automatic merges to _persistent_ branches.

It's fundamentally a backporting and cherry-picking effort, and the
git workflow puts it where it belongs: in the local repository, where
_transient_ branches can and should be created and destroyed casually
to track exploratory efforts.  These may include automatic merges and
even cruder techniques (git diff, hack on patch, apply patch).  Once
you figure out which bits you actually want to backport, you go back
to a fresh branch and cherry-pick the same bits with the tool instead
of manually, so that there is less noise in future merges.  When
you've tested a little, you merge this branch to the persistent branch
that other repositories track.

Cheers,
- Michael
-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 1:09 pm

I'm saying that even if you _never_ end up using "git fetch" ever again 
(because in practice you always want to do a "fetch + merge == pull"), 
people who teach others the concepts and usage of git should probably 
start by talking about "git fetch".

Then, when the user says (and he obviously will say this) "but I don't 
want to just fetch the other persons work into some local branch, I want 
to actually get it into _my_ branch", you say "Ahhah!" and talk about how 
"pull" is a shorthand for first fetching and then merging the result into 
the current branch.

See? Once you explain "fetch" to somebody, I can pretty much guarantee 
that they'll explain "pull" to themselves without you having to even work 
at it. And then they'll probably happily use "pull" ever after, and never 
worry about fetch, but now they'll understand the _concepts_.

It's only if you start the other way around that "pull" vs "fetch" vs 
"push" become confusing. If you _start_ by explaining branches (and you 
might use "gitk --all" on a small project as a visualization tool), 
suddenly the concepts aren't all that complicated.

Sure, then you have to remember two words ("pull" vs "fetch"), but I'm 
pretty sure that the thing that makes people confused is not the words 
themselves, but their lack of understanding of the concepts behind them.

		Linus
-

From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 1:21 pm

Actually I believe it would make things even clearer if "merge" was 
taught at that point.  Only when the user is comfortable with the 
separate notions of fetching and merging might the pull shorthand 
possibly be mentioned.


Nicolas
-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 1:40 pm

I agree. I just expect that "merge" is such a simple concept that it 
doesn't really need a whole lot of explaining. 

People kind of expect merging to be hard, but I think it's because CVS et 
al have tought people that merging is _painful_. I don't think it's a very 
complicated concept per se, especially if you have explained branches with 
gitk already.

But yes, the order should be:

 (a) explain what "branches" mean in git (and in that situation, "fetch" 
     is very natural - I think fetching itself is probably easier to 
     explain than "branches" are).
 (b) once you've explained branches, the notion of "merge" comes next, and 
     I _think_ that is very obvious. This is where UI issues come in, 
     because "git merge" is really a totally internal program with a 
     pretty horrid UI, but I think we could fix the syntax, and even with 
     the current syntax you can really just gloss it over, because nobody 
     is really going to care.
 (c) once "fetching branches" and "merging" have been explained, "pull" is 
     really pretty damn trivial, and in fact, if you then explain that 
     it's just easier to do "git pull . branchname" than to use "git 
     merge", I think people may just even agree with you.

I think I saw that particular discussion on #git: somebody didn't expect 
"git pull . branch" to be the way to merge. And again, I think it's 
not _really_ because "pull" is hard to understand, it's because people 
haven't been walked through the thing in this way.

Once you understand local branches, fetching and merging, it's actually 
_easier_ to explain why we merge even local branches with "git pull .": 
you just tell them that this way you can use the same command regardless 
of whether you're merging something local or something remote. Again, if 
it's explained that way, I bet a lot of people react with "ahh, that's 
clever", and _like_ the fact that they only really need to learn _one_ 
command, instead of learning two.

See? Explain it ...
From: Carl Worth
Date: Wednesday, November 15, 2006 - 2:08 pm

Well, one of the problems is that with current git I can teach, (and I
have), that there's a conceptual:

	pull = fetch + merge

But then shortly after I have to teach an interface notion:

	merge = pull .

So there's this goofy circular notion that people end up with
mentally. If we fix it so that a local merge really is performed with
"git merge <branch>" instead of "git pull . <branch>" then teaching
pull=fetch+merge really is a lot easier.

In the meantime, pull would still be useless to me, I think. But maybe
that's just the "default branch to merge" selection being broken. If

There's a piece missing here, namely the mapping between remote and
local branch names and any notion of "tracking branches". I think a
sane story for that is still being invented, (or if it exists now, I


No. It's really, really broken to use "pull ." for local merging. Not
a feature at all. We just got done establishing that pull is a
shorthand for doing fetch+merge, so reusing it when there is _no_
fetch at all is insane.

You just established quite clearly hat git has a huge advantge over
all other systems by having a model that everything is fetched in
and then worked with locally. I agree that this is a major
selling-point of git, and I'm also baffled that systems like bzr and
hg try so hard to push every branch into a separate repository.

But I think that git's "work with everything locally" story is undercut
a bit by regular usage being to use a transfer-inducing command like
"pull" for a totally local merge.

Anyway, I think we all agree that we'd really rather have "git merge
<branch>" be usable for local merges, so let's get that in place and

Totally agree.

-Carl
From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 2:31 pm

I am wondering if that could be "git merge <committish>..."
instead.  I do not care too much about the ... part (i.e. an
Octopus), but I often find myself doing:

	git checkout next
        git merge "Merge early part of branch 'foo'" HEAD foo~3

when earlier part of "foo" topic are worthy to be in 'next' but

Have you looked into per-branch configuration for default merge
source recently?  It might not be documented well enough,
though, because I do not use it myself, but you should be able
to improve on that (meaning both documentation and setting up
the defaults upon cloning and fetching).

-

From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 2:40 pm

Indeed !


Nicolas
-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 2:52 pm

Indeed, what?

That means that updated "git merge" (not the current one) would
not be able to assume it's parameter is a branch name, and still
has to come up with the merge message "Merge <branch>".

Merging only within the local branch namespace already has the
problem you need to solve to come up with a nicely formatted
"Merge <branch> of <remote repository>" some way.  I am not
saying that this is unsolvable (you can look at remotes/ files
to see what remote tracking branch the branch is about), but
something you need to keep in mind when implementing the
improved "git merge".

-

From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 2:59 pm

Right.  But that is an _implementation_ detail, not a usability issue.


Nicolas
-

From: Karl
Date: Friday, November 17, 2006 - 5:20 am

Often, it would be a branch or a tag, so no problem there. For commits
in general, it should not be hard to compute the set of branches and
tags the commit is part of, and in the (probably) common case where
this set has exactly one element, the problem is solved. For the
remaining cases, it should not be too horrible to ask the user to
describe what is being merged.

-- 
Karl Hasselstr
From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 2:45 pm

This is why I would suggest teaching the _concept_ of the "merge", and not 
the actual command.

I don't think you should basically ever use the "git merge" command 
itself, not in teaching, and not in real life. So after talking about 
branches and having taught people to use "git fetch", the next stage is 
not so much to teach people to use "git merge", but to explain to them the 
_concept_ of merging. 

I really think that's a fairly quick thing, partly exactly _because_ you 
shouldn't at that point need to worry about syntax or details or anything 
like that at all. You just tell them that there's a notion of "merging" 
two branches by joining them together and havign the result have the 
changes from both branches. So it's a _conceptual_ issue, and that's why I 
said I think you should just totally gloss over the whole issue of "git 
merge" syntax.

Once you've explained the _concept_ of merging, you then introduce the 
command to actually _execute_ the merge: it's "git pull".

See? No circular thinking at all. One is a _concept_ ("join two branches 
together by including both in the result") and the other is a command 
("pull will fetch the remote data if any, and merge it into the current 
branch").

If you explain it that way, then _obviously_ if you don't need to fetch 
any remote data, doing "git pull . xyzzy" will merge the local branch 
"xyzzy" into the current branch.

		Linus
-

From: Carl Worth
Date: Wednesday, November 15, 2006 - 3:52 pm

I think that's just and accident of git-merge having such a bad
syntax, (requiring a merge message, not using -m for that, requiring
two heads instead of defaulting to current, etc.). So the result is
accepting another bad syntax "pull ." for an operation that really is

I think we'll be doing better when there is a stronger correlation
between the concepts of the operations and the command names for
carrying them out.

Plus, when I'm teaching "fetch everything first, then manipulate it
locally", (which is what I teach, since that's the only way I use
git), then the "." looks really out of place when I teach the 'merge'
command. I end up saying, "Oh, that's there because you could do the
fetch and merge all in one step if you really wanted, but I never do
that.".


That doesn't work. I know I went looking at the git-merge
documentation when I started to learn git. "It can't really be this
hard, can it?" was my reaction to it. And then only after attending a
tutorial did I learn that "pull ." is the way it's really done.

That's nothing more than a user-interface trap for new users, plain
and simple.

The real fix is to stop glossing over git-merge and just give it a
usable syntax.

-Carl
From: Shawn Pearce
Date: Wednesday, November 15, 2006 - 4:02 pm

Ditto.  In every way.

I've taught the same fetch first, then merge strategy.  Nobody I
know in meat-space pulls from a remote URL and merges in one shot;
they always fetch locally, look at the incoming changes, decide if
its worthwhile/ok, *then* merge with "git pull . branch".

The "." looks out of place for everyone...

-- 
Shawn.
-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 4:33 pm

Actually, with different people involved it's _much_ better to do it in 
one shot.

Why? Because doing a separate "fetch to local space" + "merge from local 
space" actually loses the information on what you are merging.

It's a lot more useful to have a merge message like

	Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6

than one like

	Merge branch 'for-linus'

which is what you get if you fetched it first.

Of course, in a situation like git itself, where most of the merges are 
stuff that Junio has had pending in his own tree ('maint' branch etc), 
things are different. But in a system where people actually use separate 
trees, there really is an advantage to consider the fundamental operation 
to be the "pull", not the "merge".

Again, the kernel really is more distributed than most projects, but this 
is another thing people should recognize: git has been designed for "true 
distributed development". Not the "fake" kind. Not the "I merge mainly my 
own branches" kind of thing. Truly distributed.

And in a truly distributed situation, "pull" is strictly more powerful 
than a separate "fetch" + separate "merge".

In other words, an SCM that does "pull" is _better_ than an SCM that does 
"merge". You can implement "merge" as a special case of "pull" (which we 
do), but you cannot conveniently do it the other way around without having 
to tie them together some other way (ie you could have a "remember the 
last place we fetched this branch from in order to tie the fetch and the 
merge together" - but please realize that that is exactly what "pull" 
_is_).

So I will generally do a "git pull" (possibly followed by a "git reset 
--hard ORIG_HEAD" if I decided it wasn't good) over a "git fetch" + "git 
merge". Exactly because the "pull" operation is actually more powerful.

Maybe people who aren't in my position don't always appreciate the _power_ 
of git. The reason "merge" is a second-class citizen is simply because IT 
SHOULD ...
From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 5:08 pm

That is an implementation detail that should be easily overcome once the 
notion of tracking branch with URL attribute is implemented.  Then it 
will be really easy to notice whether the branch argument is a local 
branch or a tracking branch with remote reference.


Nicolas
-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 8:07 pm

Nope.

I simply don't _have_ those branches.

Why? Because the kernel is _distributed_. There is no central place 
(certainly not my repository) that tracks all the possible branches that 
might get merged.

In other words, I repeat: in a TRULY DISTRIBUTED ENVIRONMENT it makes more 
sense to have a "pull" that fetches and merges, over something that 
fetches separately and then merges. Because in a truly distributed 
environment, you simply DO NOT HAVE static branches that you can associate 
with particular sources.

See?

And the thing is, I think the git design should be geared towards true 
distribution. It should NOT be geared toward a fairly static set of 
branches that all have a fairly static set of other repositories 
associated with them. Can you see the difference?

I'm personally convinced that one of the reasons people tend to use git in 
a centralized manner is just a mental disease that has its roots in how 
they used _other_ SCM's. I don't want git design to be polluted by such a 
centralized notion.

So to repeat: you can always make "pull" boil down to "pull from myself" 
(aka just "merge"), but you can _not_ make "fetch + merge" boil down to 
"pull" without meking up extra state to track separately. In other words, 
"pull" really is the strictly more powerful operation.

			Linus
-

From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 8:43 pm

[...]

OK fine.  git-pull is there to stay and let's make sure it remains the 
same.

Let's see if, for example, git-merge can be made more useful in the mean 
time for those evidently inferior people that would prefer an interface 
that maps more closely to the actual operation that is being performed.  
And although I do understand what "pull" does, I think I should qualify 
myself as one of those inferior people nevertheless since /pull . blah" 
really irritates me.  OK I must be really dumb to let myself being 
disturbed by such an insignificant detail... but apparently I'm not 
alone.

But I promise to never change the "pull" behavior if I ever attempt to 
fix the "merge" command for the inferior mortals as myself.  All power 
to those with superior minds shall never be removed.

;-)


Nicolas
-

From: Michael K. Edwards
Date: Wednesday, November 15, 2006 - 8:02 pm

Full ACK from a platform integrator's perspective.  Local merge is
great for trial runs but the history in a persistent branch should be
as self-contained and self-explanatory as possible.  It shouldn't
depend on what I name local tracking branches, which are just a
convenience so that I can still do trial runs when my connectivity is
broken.

I don't have to manually log the _mechanical_origin_ of a given delta;
git does that for me, and mostly just DTRT when the same delta arrives
via several paths.  When I use git pull from a remote branch (with or
without an entry in remotes/heads, which for this purpose is just
shorthand), I don't have to manually log what conflicts I have and
haven't resolved, either; I must have assimilated whatever I cared
about in the remote branch's history up to that point, because as long
as there are things in that remote branch that I haven't decided how
to handle, I stick to cherry-picking.

Obviously, fetch to local space is great (especially when you spend
some of your working hours behind a firewall that blocks outbound TCP
9418).  Fetch from local space is also great, when the local space you
are fetching from reflects local work (such as a sync point and
reconciliation of several upstream sources, which then needs to be
ported forward or back to the chosen core version for each platform).
Fetch from a local space that is just a tracker for remote work is not
great, because it doesn't capture the editorial decision implied by a
remote pull:  I looked at what the remote branch had to offer as of
this date, systematically decided which bits did and didn't belong in
the branch to which I was pulling, and pulled.

The record of that pull becomes a first-class object because it's
attached to an actual content delta in the target branch.  So it
propagates into branches that pull from it.  Pulling this delta into
another branch is different from cherry-picking a feature delta; it
implies acceptance of the reconciliation and editorial work ...
From: Andreas Ericsson
Date: Thursday, November 16, 2006 - 4:35 am

I think it's unfortunate that git was originally written by Linus, since 
he so obviously is "the guy at the top of the pyramid" in many more 
senses than just "Linus said this and that patch was OK to commit", 
since git was designed to work like king Arthur's round table; "Linus is 
in the same circle as me, so ofcourse we help each other out".

All suggestions I've been reading about tracking branches, 
separate-remotes and whatnot have their merit. If any of it gets 
implemented, I'd still like to be able to do one-shot pulls from remote 
repos *without* creating specific tracking branches for it. It's 
extremely useful to fetch other peoples topic-branches into my own 
"master" (or topic-branch) when I trust their changes to be good. Please 
consider that when you're hacking away on whatever changes to do.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231
-

From: Carl Worth
Date: Thursday, November 16, 2006 - 9:37 am

There's more information in the first, sure. But I absolutely don't
accept that it's necessarily more useful, and definitely not that this
is a good argument for using pull with a remote branch instead of
fetch followed by merge with a local branch.

First, the pull may just fast-forward in which case there's no message
at all. And we've been through that topic enough recently that we all
know that no important information is lost by not doing any separate
recording in that case.

So you can't turn around and argue that the remote URL information is
suddenly important when it just so happens that it's not a fast

I don't buy it. In my usage, I have several different remote
repositories I'm interested in tracking, each with any number of
branches. What I really want is an easy command that fetches all of
those branches, (even new ones that I've never heard about---but never
any of their "tracking branches" that wouldn't be of interest to
me). And I want to do that once, to get the online-access-required
part over with and get all the data into my local repository where I
can start working with it.

As for the URL from which I'm fetching all this stuff, it's really not
interesting to me at all. The URL for "Keith's stuff" keeps changing
anyway---I have no interest in recording that. But I do think it's
worth recording that the commits came from Keith's repository. I do
that right now with a keith/ prefix for his branches. It could also be
done by bringing in his .git/description during the fetch and storing
it somewhere. But I honestly don't see how storing something like that
during would make the system any less distributed in any sense.

-Carl
From: Michael K. Edwards
Date: Thursday, November 16, 2006 - 10:57 am

When it's a fast forward, the puller hasn't had to make any judgment
calls, so there's no editorial history to record.  When it's not, but
the puller chooses to retain the result on a persistent branch, that
_is_ an editorial decision (even if the result of the auto-merge is

What do you want all of those branches for?  They haven't been
published to you (that's a human interaction that doesn't go through
git), so for all you know they're just upstream experiments, and doing
things with them is probably shooting yourself in the foot.

I do agree that a robust form of "for b in .git/remotes/*; do git
fetch `basename $b`; done" would be a nice bit of porcelain.  The
entries in .git/remotes would probably need to grow a "Fetch-options:"
field so that you could choose whether or not to follow tags, etc.
Patch to follow.

Cheers,
- Michael
-

From: Carl Worth
Date: Thursday, November 16, 2006 - 11:23 am

The same "what do you want them all for" question could be asked of
git-clone which also fetches all available branches. I really just
want to be able to easily watch what's going on in multiple
repositories.

I want to be able to just say "git update" (or whatever) and then be
able to list and browse and explore the stuff locally.

Yes, there's still outside communication that's necessary, but with
the ability to easily track all the remote branches that communication
can be even less formal if I can easily browse and explore things
locally. For example, I might not even know the name of the branch:

Me: Have you pushed a branch for your new work on the frob-widget?
Friend: Yes

And then I can "get fetch" and see "cool-new-frob" come in without
having to be told that name. Or I could have even just fetched
without the specific communication if I was already expecting it for
some reason.

-Carl
From: Junio C Hamano
Date: Friday, November 17, 2006 - 1:41 am

I have no objection to this if it is done in a controlled way
that does not make life more difficult for people who work with
multiple remote repositories.

And I think "git fetch" is the tool for what you want if
enhanced properly; see Linus's message that explaind that we
already have that support in "manually configurable" form but
initializing and maintaining the configuration is currently all
manual and can be improved.


-

From: Carl Worth
Date: Friday, November 17, 2006 - 2:18 am

That's fine with me. Maybe I didn't explain this well before, but my
desire is exactly for this to work with multiple repositories.

Specifically, what we have in cairo is a "central" shared tree that
many people push to. But we only have two branches there, (one for
bug-fixes only for our stable releases, and one for ongoing
development of new features, and that only of stuff that's well
cooked).

So that tree looks and acts an awful lot like our cvs tree back in the
past. It's often very linear and often fairly boring to look at in gitk.

Meanwhile, all the really interesting stuff happens in personal
repositories where people have their own branches for stuff that is
still getting cooked. This is what's a lot more fun to watch, and
there's a lot more distributed back-and-forth that goes on here as
people collaborate on things. And it's all this kind of collaboration
that cvs never helped with at all, but git has been great.

So, what I want is both "git update" for the central tree. I said we
only have two branches, but that's really only two that are
active---the "stable" branch is actually a new branch after every
major release. It was 1.0 for a while, is 1.2 now, and will be 1.4
later. So I want "git update" to automatically pick those new branches
up as they get created.

Meanwhile, I also want to use "git update" to track everything that
people are working on in the more wild personal trees. So, yes, I do
want "git update" to be able to track lots of remote repositories in a
sane way.

What I have been doing up to this point is a little script I wrote
that does git-ls-remote on the repository I want to track and writes a
.git/remotes file to bring in all their branches. So if I want to see
what behdad is up to, I first refresh his .git/remotes file with my:

	cairo-git-setup-remotes behdad
then:
	git fetch behdad

And I end up with a bunch of branch names with "behdad-" prefixes that
I can explore or blow away if I'm no longer interested, (could have
used a ...
From: Johannes Schindelin
Date: Friday, November 17, 2006 - 3:11 am

Hi,




I introduced the remote.<nick>.{url,fetch,push} entries into the config 
with the goal to enhance -fetch to remember the current command line with 
a setting. I was the only one to find that useful.

BTW I still would argue that it is better to write the remote information 
into the config, because you have a saner way to manipulate that from 

I think a message like "This remote branch no longer exists. Maybe you 
want to use 'git branch -d <branch>' to remove it locally?" should 

IIRC this idea was rejected, but I would find it useful. Especially with 
what Han-Wen said: you can store the branches you fetch with "git fetch 

First thought was: it is only useful if you want to track multiple 
repositories. But next thought: if you mark the correct remotes in every 
of your local repositories, you don't have to remember which nick your 
upstream has. Yeah, I like it. But maybe do it as "git fetch --update" to 
avoid more cluttering of the bindir?

Ciao,
Dscho

-

From: Junio C Hamano
Date: Friday, November 17, 2006 - 4:41 am

With separate-remote layout, this can be done without risk of
tracking refname clashing with local refname, which was the
primary reason for an earlier reluctance.  

While separate-remote layout also solves Carl's "do not want to
track tracking branches remote has" problem, local branch
namespace can have both for-others (not necessarily "public" but
could be "for colleagues") and throwaway branches, so --all is
probably not the right thing to do in most cases.  But I am Ok
with the approach of seeing how well it works out in practice by
doing the simplest "--all" and giving options to restrict it
later.

-

From: Shawn Pearce
Date: Friday, November 17, 2006 - 9:58 am

I'm *fully* in favor of the remote.<nick>.{url,fetch,push} entries
in the config file.  I've pretty much switched every repository to
that format at this point.

In writing git-gui I'm finding it much, much easier to manage
things through repo-config than to do any mucking around in the
.git/remotes directory.  Yes, the remote files have simple format,
but I can get everything in one "git repo-config --list" pull it
all into a Tcl array and work with it; using .git/remotes means I
have to open the file and read each line too.  :-(

-- 
Shawn.
-

From: Junio C Hamano
Date: Friday, November 17, 2006 - 4:29 am

This already should be the case if you use separate-remote.  I
haven't run "clone --separate-remote" myself for a long time,
but the design was certainly to make it behave that way.
Specifically, map everything in refs/heads/ at remote to
refs/remotes/$origin/ with corresponding names, one-to-one.

I do not see much reason to change the mapping of master:origin
which is done for the traditional layout.  The traditional
layout is not suitable for your workflow anyway, and that is why
you prefer separate-remote layout for your project, and I fully

These three are easily done for separate-remote layout but at
that point you would not want --all but more powerful --mirror
(or --update if you want to use that word), which goes the whole
nine yards of noticing disappearance of remote branch, making
matching deletion of local tracking branch, updating
.git/remotes, etc.  I've muttered something similar in a nearby

I would prefer this to be kept in contrib/; it feels like it is

I muttered something less elaborate in the nearby thread.

	Message-ID: <7vr6w78b4x.fsf@assigned-by-dhcp.cox.net>
	Message-ID: <7v64dev88t.fsf@assigned-by-dhcp.cox.net>

The part that deals with manual configuration (the last point in
the first message, and the second in message its entirety) is
something your workflow would not need nor want to worry about,
but I think it is necessary for different ref namespace layouts
and different workflows.  I think the automatable part (the
first two points in the "sensible thing to do" list in the first
message) is very relevant to what you talked about in your
message.

-

From: Sean
Date: Wednesday, November 15, 2006 - 4:07 pm

On Wed, 15 Nov 2006 14:52:32 -0800

Agreed 100%   There's just no good reason to hide the user level
merge command inside of pull.

Sean.
-

From: Jerome Lovy
Date: Tuesday, November 21, 2006 - 6:25 am

On a conceptual level, can we not perhaps explain that if

	pull = fetch + merge

then

	merge = pull - fetch

and that the latter (pull - fetch) happens to be expressed with the 
interface as 'git pull .' ?

My 2 cents.
J
From: Theodore Tso
Date: Wednesday, November 15, 2006 - 9:26 pm

Actually, that's not true.  Mercurial has local branches, just as git
does.  Some people choose not to *use* this particular feature, and
use the BK style repository == branch, but that's mainly because it's
conceptually easy for them, and a number of BK refugees are very
happily using Hg.  

It's probably because of the BK refugee population that after you do
an hg pull, it will warn you that you need to do an "hg update" in
order to merge the working directory up to the latest version that was
just pulled --- and this change was made precisely because Hg supports
local branches, and merging with the current branch isn't always the

It's just that the semantics are different, and many developers have
to use multiple DSCM's, depending on what project they happen to be
developing on.  So the reality is that there are people who have to
use bzr, git, and hg, all at the same time.  And while eventually
newbies will figure out and remember that "git pull ." == "merge", the
naming is simply confusing, that's all.  (What does "pull" have to do
with "merge"?  It's not at all obvious.)  

For somoene who uses git full-time, and to the exclusion of all other
systems, I'm sure it's not a problem at all.
	
					- Ted
-

From: Andreas Ericsson
Date: Thursday, November 16, 2006 - 4:50 am

It seems we should, cheaply, be able to avoid a large part of the 
confusion by

* Mentioning git-fetch before git-pull in all documentation newborn 
gitizens are likely to come across. Most git-users aren't Linus, and for 
every successful project the maintainers are outnumbered 100 to 1 by the 
contributors. Those projects successful *because* maintainers are 
heavily outnumbered so we should make it easier for contributors by 
teaching them the right things from the start and possibly have a 
separate man-page for maintainer (git-{maintainer,developer} man-pages, 
anyone?).
* Creating "git update" which might possibly be an internal alias to 
"git pull", except that it should read .git/remotes/* by default unless 
a specific remotes-file is specified.
* Renaming git-merge to git-merge-driver
* Implementing a git-merge that actually does what its name implies, 
possibly by making it an internal alias to pull, but with these differences:
   - It always merges into your current branch.
   - It understands "git merge branch" as well as "git merge . branch".

This is just the very low-hanging fruit. If we take these steps and let 
things cool down a bit, it would probably be proper to take a fresh look 
at this in a couple of months.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231
-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 9:30 am

However, I also think it might make sense to talk about the _simple_ form 
of "git pull" first.

The form I use is actually a lot simpler (conceptually) than the "short" 
form.

When you do

	git pull <reponame> <branchname>

there are very few things that can confuse you (although trying to do it 
without a current branch at all is apparently one such thing ;). 

There are no local branches to worry about, and there aren't any issues 
about what the default repository or branchname on the remote side would 
be either.

So in many ways, if you use this format, you simply never have to worry. 
You may have to _type_ a bit more, so it's not the short or concise 
format, but it sure is the _simple_ format. There simply isn't anything to 
be confused about.

And yes, I actually tend to use this even for project that I don't develop 
on, partly because the defaults for the short and concise formats are bad. 
For example, I follow the "modesetting" branch on the xorg intel graphics 
driver tree, and because I'm always on that branch, what I do is

	git pull origin modesetting

which works correctly (while "git pull" would _not_ have done the right 
thing: it would have picked the right repository, but it would have picked 
the "master" branch of that repository, not the "modesetting" branch).

And notice how I don't do _any_ development there, I just follow that 
branch. The "merge" will obviously always be a fast-forward, but that's 

Well, as mentioned, I think even for non-developers, doing pulls with 
explicit branchnames is actually perfectly sane.

		Linus
-

From: Carl Worth
Date: Thursday, November 16, 2006 - 10:01 am

Yes, that's what the user almost always wants. The UI problem here is
that the conceptually simpler form is syntactically longer, (which
means users aren't likely to find it).

So if we can just get <reponame> and <branchname> to default
correctly, (based on the current branch name, and clone/fetch/pull
history), then the conceptually simple form ends up syntactically
simple as "git pull".

And I definitely don't have any problem with that. I'd love to be able

The behavior is sane, but having to always type the branch name
specifically because it never changes... that's a user-interface bug.

This is a good example of the kind of thing I wanted to hit when
starting this thread. I don't think there are any big conceptual
changes needed in git to make it easier for new users. But there are
little things that are problems that really should be fixed. Wouldn't
it be great to have the following exchange:

	User: How do I track on-going development in a branch?
	Master: Use "git pull"

Rather than:

	User: How do I track on-going development in a branch?
	Master Use "git pull origin <name-of-branch-you-are-already-on>"

?

-Carl
From: Linus Torvalds
Date: Thursday, November 16, 2006 - 10:30 am

Yeah. 

And this is something I absolutely agree with. Our default branches for 
"pull" are horrible. You can "fix" it, but you can only fix it by adding 
_explicit_ branches to your .git/config file by hand, so I don't think 
that's actually a real fix at all. We should just fix the default (where 
even a "I don't know what branch you want" _error_ would be preferable 
over the current situation).

Along with the "git checkout <tag>" thing, I think these two things are 

Yeah. Each branch should

 (a) have a "default source" initialized on the initial "clone"

 (b) have a way to set the source afterwards

 (c) error out if you do just a "git pull" or "git pull remotename" if 
     there is no default branch for the current local branch for that 
     remote.

We actually have (b) in a weak form right now ("weak" because it requires 
you to manually edit the config file: we've got the mechanism, but not a 
nice UI for it), but (a) and (c) are just broken.

And yeah, we should allow pulling into a branch that hasn't been 
initialized.

		Linus
-

From: Sean
Date: Thursday, November 16, 2006 - 10:44 am

On Thu, 16 Nov 2006 09:30:47 -0800 (PST)

This would be _great_.  You just shouldn't have to hack at the
.git/config file to get reasonable default sources after a clone.
Or even for that matter after fetching a new branch into an
existing repo.

Sean
-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 12:32 pm

We usually use the word "regression" to refer to that kind of
change.

I think it makes a lot of sense having command x that does
essentially the same thing as the current fetch but with more
usability enhancements and more convention as built-in defaults,
and another command y that does what the current 'pull .' does
but with more usability enhancements and more convention as
built-in defaults.  I agree that kind of UI improvements would
make it easier to explain to new people.  Calling x "pull",
however, breaks the existing users and documents, and causes
confusion.  I really do not think you can argue with that.

That's why we are talking about using an uncontaminated word

And I think Linus is right in pointing out that there are other
problems that are equally or even more pressing than _renaming_
to break things for existing users.

I personally do not think the current fetch/pull confusing, and
I do see real downside in _renaming_ them, but I am open to the
current get/put discussion because I think the new commands'
semantics may be designed to match newcomers' expectation better
(it's to match tools to newcomers instead of teaching them the
new language of the land) and I do not think that approach would
break existing users and documents.

For some things "matching tools to newcomers" would not really
work, though.  For example, I do not think you can get away with
hiding index forever if you want your users to do real work in a
workflow that involves merging and cherry picking.


-

From: Han-Wen Nienhuys
Date: Wednesday, November 15, 2006 - 6:20 pm

that's not a good argument; the set of git users is a small subset of 
those that looked at git, and dismissed it because they couldn't wrap 
their heads around it.   It's worth trying to get those on board by 
fixing the annoying little issues that have popped up in this thread. 
The technical base for GIT is excellent, and the only reason for not 
using it is its arcane interface.

A version control system is often only tangentially related to the real 
work that needs to be done, so the incentive to learn it well is small, 
   and a steep learning curve only makes it worse.

FWIW, I regularly mess up with the differences between fetching, pulling 
and merging.  In particular, having to do a two step process to get 
remote changes in,

   git pull url-to-server master:master
      ..error message about not being a fast-forward..

   git pull --update-head-ok url-to-server master:master
      ..still an error message about update not being a fast-forward..

       (sigh)

   git pull url-to-server master:scrap-branch

   git pull . scrap-branch:my-current-branch

       (make mental note of deleting scrap-branch)


-- 
  Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 7:03 pm

Sigh indeed.

Why don't you do the simple and obvious

	git pull url master

or "git pull url" if you already know the master is the branch
you are interested in.

The more advanced form of using tracking branches are there and
documentation talks about them for completeness but that does
not mean you have to use it.

-

From: Han-Wen Nienhuys
Date: Wednesday, November 15, 2006 - 7:30 pm

It is not all evident from the git-pull man-page that this is the 

Because I usually replace verbose commands with shortcuts only when I 
understand exactly what the shortcut is.

To me it's very unlogical that

   master:current-branch

doesn't work, but

   master:

does work, and does what I'd expect

   master:current-branch

to do. Interestingly, doing

   pull ..url.. master:HEAD

also doesn't merge into the current branch, but rather creates a bogus 
refs/heads/HEAD

I use the remote:local syntax, because I started using GIT in scripted 
compiles from copied branches of remote repositories. There the explicit 
remote:local statements are necessary because there is no default branch.

-- 
  Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 8:27 pm

In the git user poll a few months ago, many people recommended
"everyday git" as a good cheat sheet, and indeed it does not
talk anything about directing the underlying git-fetch to
manipulate tracking branches by giving explicit refspec pairs to
git pull.  You are obviously tripped by both the overeager
manpage (but manpage should strive to be complete so you cannot
really blame it) and less than optimally organized tutorial
style documents.

I myself do prefer, when learning a new tool, to use longhand
until I understand the shorthand, but that attitude requires a
true commitment to learn the tool, and most people do not go
that route.  Tutorial style documents tend to give the commonly
used shorthand first for that exact reason.

Shorthand to give only the branch name to fetch and merge
immediately without using a tracking branch is equivalent to
longhand "branch:" as you found out, so if that was what was
desired then people with the attitude "before understanding what
longhand does I prefer using shorthand" like myself and you
would have liked to learn "git pull url branch:" notation from
Tutorial.  But I think we _are_ minority.  People would not want

That shows that you did not understand what fetch does.  Maybe
you do now, but a very natural consequence of directing fetch to
update tracking branches with the colon notation is:

 - "pull url master:master", while on master, is almost always
   wrong and not something you would want to do, ever.

   "fetch --update-head-ok url +master:master; reset --hard HEAD"


If you perhaps wanted to ask "is there a better way to do what
I've been doing?", then I am willing to think with you to come
up with an answer.  Unfortunately, however, I do not understand
the above paragraph, so I'd refrain from commenting on it in
this response.



-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 8:35 pm

Junio C Hamano <junkio@cox.net> writes:


Eh, sorry, "prefer to use longhand until I understand what is


-

From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 9:07 pm

Sorry, I must have been very grumpy mood when I wrote the
message (cf. Pasky's utterance on #git a few days ago).  What I
wrote was a bit incoherent, so here is an attempt to clarify.

I should point out that the colon separated refspec pairs you
can give to "pull" was designed with considerable thought; it is
not a convenience hack that we give them to "pull" that "fetches
and merges".  Linus's and Michael's other messages in this
thread may seem to be saying that using tracking branches is not
a kosher way to use git, but I do not think that is a correct
interpretation of their messages.

The workflow that does not use any tracking branches is the
simplest and truly distributed way as Linus says.  The command
recommended in "everyday git" document:

	git pull $url $branchname

is the most natural way to express it, and simplest variant that
you do not have to say anything "colon" in it.

However that does not mean it is a bad practice to use tracking
branches.  Sometimes it is handy to be able to refer to what you
fetched from the remote the last time, possibly which is what
you merged into your branch if that last fetch was done via "git
pull", so that you can later examine its history without your
own development.  For that purpose, you need to store what you
fetched in your local refs/ namespace, and that is what tracking
branches are.

The workflow that fetches to tracking branches and then merges
within local repository as two separate steps loses the true
origin information ("Merge branch 'foo'" vs "Merge branch 'foo'
of git://git.bar.xz/foo.git").  That's the reason why not just
"git fetch" but also "git pull" take the colon separated refspec
pairs to direct git to update the tracking branches when "pull"
happenes.  The longhands are cumbersome to type all the time,
and we have shorthand, both to store URL: and Pull: lines in
remotes/ hierarchy, and also $branchname alone is a shorthand
for saying "${branchname}:", meaning "do not use a tracking
branch to ...
From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 8:12 pm

And I've said this again, and I'll say it once more: that has basically 
_nothing_ to do with whether you spell "pull" as "pull" or "merge".

The reason people have trouble wrapping their heads around git is because 
they have been braindamaged by CVS and SVN, and just don't understand the 
fairly fundamental new concepts and workflow.

That's totally different from then arguing about stupid naming issues.

Peopel seem to believe that changign a few names or doing other totally 
_minimal_ UI changes would somehow magically make things understandable. I 
claim that isn't so at all. The fact is, git is different from CVS and 
SVN, and git _has_ to be different from CVS and SVN. It has to be 
different because the whole model of CVS and SVN is simpyl fundamentally 

I claim that those "annoying little issues" are totally made up by people 
who had trouble wrapping their minds about git, and then make up reasons 
that have nothing to do with reality for why that might be so.

Let's face it, you could just alias "merge" to "pull", and it wouldn't 
really change ANYTHING. You'd still have to learn the new model. 

		Linus
-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 3:45 am

> I claim that those "annoying little issues" are totally made up by
 > people
 > who had trouble wrapping their minds about git, and then make up
 > reasons
 > that have nothing to do with reality for why that might be so.

Let me put this more personally: I continue to be bitten by stupid 
naming issues, and the myriad of little mostly non-orthogonal commands.
My head is doing just fine otherwise, and has no problems wrapping it 
around the core of GIT.  I've also used Darcs for almost a year. Darcs, 
which is much less overwhelming.

This is not about CVS or SVN, so don't put them up as a strawman.
If you want to argue that my brain is warped, use other distributed VCs 
as an example.

The following

   mkdir x y
   cd x
   hg init
   echo hoi > bla
   hg add
   hg commit -m 'yes, I am also too stupid to refuse explicit empty 
commit messages'
   cd ../y
   hg init
   hg pull ../x

pretty much works the same in Darcs, bzr and mercurial.

With GIT, this is what happens

[hanwen@haring y]$ git pull ../x
fatal: Needed a single revision
Pulling into a black hole?

[hanwen@haring y]$ git fetch ../x
warning: no common commits
remote: Generating pack...
Done counting 3 objects.
Deltifying 3 objects.
  100% (3/3) done
Total 3, wremote: ritten 3 (delta 0), reused 0 (delta 0)
Unpacking 3 objects
  100% (3/3) done

[hanwen@haring y]$ git checkout
fatal: ambiguous argument 'HEAD': unknown revision or path not in the 
working tree.
Use '--' to separate paths from revisions
fatal: Not a valid object name HEAD

[hanwen@haring y]$ git branch master
fatal: Needed a single revision

at this point, I resort to adding a bogus commit and/or editing 
.git/HEAD by hand. I'm sure there is a saner way of doing it, but I 
still haven't found out what it is.

This might not be typical GIT use, but it does show the typical GIT user 
experience, at least mine.

If you want to have another example of how not to design a 

I don't want ANYTHING to really change, I just ...
From: Junio C Hamano
Date: Thursday, November 16, 2006 - 4:11 am

Han-Wen Nienhuys <hanwen@xs4all.nl> writes:


You asked it to fetch from the neighbour repository and merge it
into your current branch which does not exist (I presume that
you omitted to describe what you did in directory y/ and I am
assuming you did "mkdir y && cd y && git initdb" and nothing

You fetched without telling it in which tracking branch to store
what you fetched, and as a result your HEAD is not updated, so
your current branch still does not exist.  A failure from
checking out nothingness is not an interface issue; expectation

You are not at any commit yet and you try to create a branch?

Of course, the "right" (in some sense of the word) thing is to
do "git clone x y" in the parent directory, without creating y
upfront.

If you have an empty y to begin with, then you can do this:

	$ git fetch ../x :origin
        $ git reset --hard origin

which would mirror a part of what "git clone" would have done
for you.  It copies from the other repository, stores the tip in
your tracking branch called "origin", and make your HEAD to be
the same as origin.  After these two commands, you would have
two branches, origin and master, and you will be on master.

You can name 'origin' any way you want.  You might want to name
it 'x' to make it clear (to yourself) that it is used to track
what will happen in the neighboring repository 'x'.  Also, you
would most likely be fetching and merging from the same ../x
from now on, so it might be handy to set up the remotes for it:

	$ cat >.git/remotes/x <<EOF
        URL: ../x
        Pull: master:origin
	EOF

Then subsequent work of yours would be done on 'master' branch
(you have only two branches, and origin is a tracking branch so
you will never make commits on it, which means the above is a
logical consequence), and from time to time you would sync with
whoever is working in ../x

	$ git pull x

Here, 'x' is just a shorthand which looks up the URL: and Pull: line
through .git/remotes/x.  If your .git/remotes/ ...
From: Junio C Hamano
Date: Thursday, November 16, 2006 - 4:47 am

Having said all that, I happen to think that this particular
case of pulling into void could deserve to be special cased to
pretend it is a fast forward (after all, nothingness is an
ancestor of anything), if only to make new people's first
experience more pleasant.

Working from nothingness is something not usually done in
everyday work, so from practical and technical point of view it
does not add much _real_ value to the people who actually uses
the system, but nevertheless, new people typically start
learning the system from either cloned repository (which I
believe is covered by the existing tools fairly well) or
emptiness (which bitten us here in a bad way), and making the
first experience more pleasnt to new people have a positive
value of flattening the learning curve.

So please consider that this is classified as a bug.

-

From: Horst H. von Brand
Date: Monday, November 20, 2006 - 12:44 pm

If you make pushing into an empty repository work also, you fix the case of
"create an empty repo for somebody, let them fill it up remotely later".


Thanks!
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                    Fono: +56 32 2654431
Universidad Tecnica Federico Santa Maria             +56 32 2654239
Casilla 110-V, Valparaiso, Chile               Fax:  +56 32 2797513
-

From: Shawn Pearce
Date: Monday, November 20, 2006 - 12:46 pm

This seems to work just fine now.  I do it all of the time.

-- 
Shawn.
-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 6:03 am

>> I don't want ANYTHING to really change, I just want a sane interface 
 >> to it.
 >
 > I agree that you do not want to change anything.  You just
 > needed a bit of handholding, because you deviated from the
 > cookbook usage, to correct your course.

Users (well, I do at least) start fiddling with systems to find out how 
they work.   Reading the manual is usually done as a last resort. I 
think this is pretty well documented in usability research.

I'm trying to show how GIT is badly suited to this. Your response is to 
explain to me what I should have done. That's nice, but that approach 
doesn't scale, because you don't reach the dozens of users out there who 
try the same, fail and give up.

If you really want to find out the weaknesses, you'd have to sit someone 
new to git in front of a computer, and let him figure how to operate it, 
while videotaping everything.

Writing a manual for newbies is also an effective (and simpler and 
cheaper) approach of figuring out what needs to be changed.



As another example:  annoyances regarding program invocation

  - option handling: -x -f -z != -xfz , "--max-count 1" doesn't work, 
but needs an '='

  - git --help lists an unordered set, which is too long scan quickly. 
I'd expect that list to either contain everything or the minimum set for 
daily use. I.e. the set introduced in a first tutorial.  Why are merge, 
prune, verify-tag there?

Try "bzr help" for comparison.

  - --pretty option with wholly uninformative options full, medium, 
short, raw.  It's not even documented what each option does.


I can go on with listing idiosyncrasies, but my point is not to get help 

as you remark in the other reply, there is IMO no reason for not having 
an empty 'master' branch. If master + HEAD gets created on the first 
commit, it might as well be created on the init-db.

-- 
  Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 6:11 am

oh, and another annoying one: git's insistence on firing up a pager if 
there is nothing to page, eg. try

   git-log je-n-existe-pas

-- 
  Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 9:23 am

Your example has nothing at all to do with "pull" vs "fetch", though.

Your example is about something totally _different_, namely that under 

Bzzt. This is where you went wrong, and you blamed "pull".

The way you do this in git is to NOT do "git init". Instead, you replace 
all the

	mkdir y
	cd ../y
	hg init
	hg pull ../x

with a simple

	git clone x y

and YOU ARE DONE.

Now, we could certainly _make_ "git pull" work on an empty git project, 
but that has _nothing_ to do with what people have been talking about.

In fact, the fact that "git fetch" kind of works is not exactly accidental 
(because "git fetch" _is_ meant to add new local branches too), but all 
the problems you have with it are due to the SAME issue. You started 
without any branch at all, because you started with an empty git repo, and 
you're simply not _supposed_ to do that.

So current rule (and this is not new, it's always been true): the ONLY 
time you use "git init-db" is when you are going to start a totally new 
project. Never _ever_ otherwise. If you want to track another project, use 

It's not that it isn't typical, it's that you are using the wrong model. 
Maybe it's not well documented, I can easily give you that, but ALL your 
problems come from that fundamental starting point: you shouldn't have 
used "git init-db" in the first place.

Somebody want to document it?

Alternatively, we certainly _could_ make "git pull" just accept an empty 
git repo, and make it basically create the current branch.


The sane interface _exists_. It's called "git clone".

		Linus
-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 9:42 am

Actually, only a 2 weeks ago, you suggested that I share the website
and main source code for my project in a single repository for reasons
of organization.

In this setup I find it logical to do

  git init-db
  git pull ..url.. website/master

to wind up with just the 5mb website, instead of the complete 70mb

Yes, I would like that.  


-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 10:17 am

I don't disagree per se. It should be easy to support, it's just that it's 
not traditionally been something we've ever done.

So the way you'd normally set up a single repo that contains multiple 
other existing repositories is to basically start with one ("git clone") 
and then add the other branches and "git fetch" them.

So again, instead of "git init-db" + "git pull", you'd just use "git 
clone" instead.

Note that there _is_ another difference between "git pull" and 
"fetch+merge". The difference being that "git pull" implicitly does the 
checkout for you (I say "implicitly", because that's the way the git 
merge conceptually works: we always merge in the working tree. That's not 
the only way it _could_ be done, though - for trivial merges, we could do 
them without any working tree at all, but we don't suppotr that).

And that "git pull" semantic actually means that if you want a _bare_ 
repository, I think "git --bare init-db" + "git --bare fetch" actually 
does exactly the right thing right now too. But "git pull" would not be 
the right thing to use.

Btw, another normal way to generate a central "multi-headed repo" for is 
to not use "pull" or "fetch" or "clone" at ALL, but I would likely do 
something like

	mkdir central-repo
	cd central-repo
	git --bare init-db

and that's it. You now have a central repository, and you _never_ touch it 
again in the central place except to repack it and do other "maintenance" 
(eg pruning, fsck, whatever).

Instead, from the _outside_, you'd probably just do

	git push central-repo mybranch:refs/heads/central-branch-name

(actually, you'd probably set up that branch-name translation of 
"mybranch:refs/heads/central-branch-name" in your remote description, but 
I'm writing it out in full as an example).

So there are many ways to do it. It just happens that "git init-db" 
followed by "git pull" is not one of them ;)

(And the real reason for that is simple: "git pull" simply wants to have 
something to _start_ ...
From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 10:40 am

You're misunderstanding me: the multi-repo is at git.sv.gnu.org is the
remote one. The example I gave was about locally creating a single
project repo from a remote multiproject repo. 

On a tangent: why is there no reverse-clone?  I have no shell access
to the machine, so when I created the remote repo, I had to push, and
ended up putting 1.2 Gb data on the server.

<looks at manpage>

is this send-pack? From UI perspective it would be nice if this could
also be done with clone,


yes, this works. Two remarks:


* it needs

  website/master:master

otherwise you still don't have a branch.

* why are objects downloaded twice?  If I do

  git --bare fetch git://git.sv.gnu.org/lilypond.git web/master

it downloads stuff, but I don't get a branch. If I then do 

  git --bare fetch git://git.sv.gnu.org/lilypond.git web/master:master

it downloads the same stuff again. 

-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 11:21 am

Ahh.

Ok, try the patch I just sent out, and see if it works for you. It 
_should_ allow you to do exactly that

	mkdir new-repo
	cd new-repo
	git init-db
	git pull <remote> <onehead>

and now your "master" branch should be initialized to "onehead".

Oh, except I just realized that I forgot to do a "git checkout" in my 
patch, so you'd need to add that (or do it by hand, but you really 
shouldn't need to, since the checkout is implied by the "pull").

The downside with this is that it does NOT populate your "remotes" 
information (like "git clone" would have done), so either we'd need to 
teach "git pull" to do that too, or you just have to do it by hand (so 

Yeah, you're supposed to "init-db" and "push". Right now, that tends to 
unpack everything (which is bad), although that is hopefully getting fixed 

"git push" uses send-pack internally, you shouldn't ever need to use it 

The creation of a new archive tends to need special rights (with _real_ 
ssh access and a shell you could do it, but "ssh+git" really means "git 
protocol over a connection that was opened with ssh, but doesn't 
necessarily have a real shell at the other end").

So for most protocols, you simply cannot (and shouldn't) do it. Think 
about services like the one that Pasky has set up, that allow you to set 
up a new git repo - the setup phase really _has_ to be separate (because 
you need to set up your keys etc).

So I think the above syntax is actually not a good one, because it cannot 
work in the general case. It's much better to get used to setting up a 
repo first, and then pushing into it, and just accepting that it's a 
two-phase thing.

Also, from a bandwidth standpoint, you can often (although obviously not 
always) make the setup start with something that is _closer_ to what you 
want to do. So, for example, you'd often do something like:

 (a) ssh to central repository
 (b) create the new repository by cloning it _locally_ at the central 
     place from some other ...
From: Junio C Hamano
Date: Thursday, November 16, 2006 - 11:33 am

Saw.

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 12:01 pm

Btw, the magic heads are probably not all that well documented. They do 
come up in the man-pages, but I don't think there is any central place 
talking about them. We have:

 - "HEAD" itself, which is obviously the default pointer for a lot of 
   operations, and that specifies the current branch (ie it should 
   currently always be a symref, although we've talked about relaxing 
   that)

 - "ORIG_HEAD" is very useful indeed, and it's the head _before_ a merge 
   (or some other operations, like "git rebase" and "git reset": think of 
   it as a "original head before we did some uncontrolled operation 
   where we otherwise can't use HEAD^ or similar")

   I use "gitk ORIG_HEAD.." a lot, and if I don't like something I see 
   when I do it, I end up doing "git reset --hard ORIG_HEAD" to undo a 
   pull I've done. This is important exactly because ORIG_HEAD is _not_ 
   the same as the first parent of a merge, since a merge could have been 
   just a fast-forward.

 - "FETCH_HEAD" as mentioned. Normally you'd only use this in scripting, I 
   suspect, but it's potentially useful if you prefer to do a fetch first 
   and then check out it (perhaps cherry-picking stuff instead of merging, 
   for example).

   So you could do (for example)

	git fetch some-other-repo branch
	gitk ..FETCH_HEAD
	git cherry-pick <some-particular-commit-you-picked>

 - "MERGE_HEAD" is kind of the opposite of "ORIG_HEAD" when you're in 
   the middle of a merge: it's the "other" branch that you're merging.

   It's mainly useful for merge resolution, ie

	git log -p HEAD...MERGE_HEAD -- some/file/with/conflicts

   is a great way to see what happened along both branches (note the 
   _triple_ dot: it's a symmetric difference), to see _why_ the confict 
   happened.

Most of the above are used implicitly in various cases, not just HEAD. The 
"--merge" flag to git-rev-list (and thus git log and friends) is just 
shorthand for the above "HEAD...MERGE_HEAD" behaviour (with the addition ...
From: Shawn Pearce
Date: Friday, November 17, 2006 - 9:26 am

Although if you have reflog enabled on your current branch there
is a 1 character shorter syntax:

	gitk HEAD@{1}..

as recent Git understands that to mean the value that HEAD just had,
which is also what is in ORIG_HEAD.  Except that unlike ORIG_HEAD
it can also show even older values (e.g. HEAD@{3}, 3 ops back)
and it works very, very well on tracking branches.  "What did I
just fetch in next?" `git log next@{1}..next`

-- 
Shawn.
-

From: Linus Torvalds
Date: Friday, November 17, 2006 - 9:45 am

Heh. With a finnish keyboard, that "@" is AltGr+'2', and the '{'/'}' is 
AltGr+'7'/'0', I guarantee that it's not "1 character shorter", it's 
"three pretty complicated characters longer" and "off the normal path 
where you hold your fingers on the keyboard ;)

And that's not even mentioning that '{'/'}' is a magic sequence for 
filename expansion to the shell, so every time I see that, I have to think 
about it (and it turns out that because there is no comma in between 
there, it's ok. Otherwise you would need to quote it or escape them...)

So the reflog syntax is fine, but it's definitely not a "simple" syntax. 
I'd only use it for things where I want something that ORIG_HEAD won't 
give me ("ORIG_HEAD" you can type by just holding the shift key down all 
the time, and letting your fingers dance over the keyboard, both on a US 
and a Finnish keyboard).

And yes, I actually use a Finnish keyboard, still. Don't ask me why. I 
don't actually need the 
From: Carl Worth
Date: Friday, November 17, 2006 - 9:51 am

It's not even all that convenient on a U.S. keyboard. My pinky suffers
a bit having to pop on and off of shift for the '{', '1', '}'. Then
again, I don't like having to hold shift down for all of ORIG_HEAD
either, (but it's definitely easier in comparison).

But since reflog does everything ORIG_HEAD does and more, shall we
just clean up the syntax somehow? Ideas anyone? And then fix the
documentation to explain that?

-Carl
From: Shawn Pearce
Date: Friday, November 17, 2006 - 10:08 am

I forgot that you use a finnish keyboard.  :-)

I agree with you; its not easier to type, for you.  Me, I'm a dumb
American who uses a Kinesis keyboard, therefore my left foot is
my shift key and its in sync with my fingers.  I have no extra
pinky load for either syntax.  And since the reflog syntax works
in a lot more contexts (e.g. after a fetch into a tracking branch)
I have just forgotten about ORIG_HEAD entirely.  Oh sure, I know
its there, but its not something I think about using...

-- 
Shawn.
-

From: Carl Worth
Date: Friday, November 17, 2006 - 9:46 am

Yes, this was my exact thought when reading what Linus
wrote. ORIG_HEAD might be fine and all, but it pales in functionality
compared to what reflog provides.

I would very much like to see reflog getting first-class citizen
support in git:

1. Be on by default

2. Get documented in all the right places, (much better than adding
   documentation for ORIG_HEAD in my opinion)

3. Tighter integration with branch manipulations. Do we already delete
   reflog when deleting a branch? We don't have a branch rename
   operation, but if we get one, renaming the reflog should go
   hand-in-hand, etc.

-Carl
From: Shawn Pearce
Date: Friday, November 17, 2006 - 10:15 am

I have:

	git repo-config --global core.logAllRefUpdates true

especially since Junio fixed it to only create logs for heads and
not tags.  That way its on by default for me.  But I think it should

Agreed.  I'm not likely to do it anytime soon however, so I'm hoping

Yes, we delete the log when we delete the branch, and we prune
back the empty directories too just like we do on the branch side,
so that new branches can be correctly created.

There was a recent discussion about that from Junio if I recall.
Several people that I work with have asked that branch rename
support be added to Git, and that if you rename the branch the
reflog follows.  Because in their mind they are simply changing
the name of the branch, any old history of that branch should
stick around.

I tried to think of an option to "git branch" to do the rename but
kept thinking that:

	git rename-branch old new

is the better syntax...  even though that's command number 133
or something like that...

We should stick a "null" event into the reflog during a branch
rename.  Make both the old and new SHA1 the current SHA1 but drop
a message in saying "renamed branch old -> new" (for example).

-- 
Shawn.
-

From: Marko Macek
Date: Friday, November 17, 2006 - 10:50 am

Why is it not useful for tags for having logs? 

I also have a question:

Does git-fsck-objects/prune check the ref logs?

Mark

-

From: Junio C Hamano
Date: Friday, November 17, 2006 - 1:24 pm

When I make a tag that says "this is the v1.2.0 release", it is
expected it won't change in the future, ever.  I _can_ make
mistake and tag a wrong commit under v1.2.0 name, in which case
I may have to replace it with another corrected tag, but
recoding that mistake does not really add value.  So most of the
time ref-log for a tag would contain only one entry per file, its
creation, but that creation time is already recorded in the tag
object itself anyway.

At times, it may be useful to have some floating tag that point
at the "latest", or "today's", but that use is a minority.  For
these minority cases, you can manually create an empty file
under .git/logs/ directory to record their updates.

The configuration mechanism only kicks in when there is no such
existing file to prime the process, and not creating ref-log for

They deliberately ignore ref-log for the same reason lost-found
does not drop found refs under .git/refs hierarchy.

This only matters if you somehow rewind an existing branch in
order to lose part of its history, using "reset --hard HEAD~n"
or "rebase".  If the updates to your branch tips always build on
top of the previous (either by commiting on top of the current,
merging on top of the current, or fast-forwarding), and if you
never rewind the branch, the commits recorded in the ref-log for
the branch are always ancestors of the tip of the branch, so
checking ref-log does not give you anything other than slowing
the operation down.

However, if you rewind the tip of a branch, the story changes.
Until the next "prune", objects reachable from the ref-log of
the branch but not reachable from the tip of the branch are
still available in your object store and in a pinch you can
recover them, but after a "prune" they will be lost forever if
they do not have any other references.  So it might seem that
they should be protected from pruning.

But if you did so, you can never remove cruft from your object
store once you make a mistake.  You can clean up ...
From: Junio C Hamano
Date: Friday, November 17, 2006 - 10:39 am

Are you sure about this?  I've seen "next@{1}" to look at
history of the named branch, but never history of "HEAD".

-

From: Shawn Pearce
Date: Friday, November 17, 2006 - 11:02 pm

Yes.  :-)

If the ref name is a symref then we resolve the symref all the
way down to the real ref before we open and walk the reflog.
Therefore this works.

-- 
Shawn.
-

From: Junio C Hamano
Date: Saturday, November 18, 2006 - 12:31 am

True, except if you did:

        $ git pull
        $ git checkout otherbranch
        $ git show HEAD@{1}

My real point was that I was wondering if it also makes sense
for ref-log to record switching branches for the symref itself.

But after sending that message I thought about it a bit more and
concluded that it is not an interesting information.  It is more
code that affects unrelated places even if we were to implement
it and without real gain, so let's not log symref itself and
keep the current implementation.



-

From: Shawn Pearce
Date: Saturday, November 18, 2006 - 12:45 am

I agree completely.

I have no interest in a history of what branches I've recently
been on.  All I care about is the history of this branch.  And I
consider HEAD to be nothing but a shortcut that always points to
the current branch... so its darn useful for that.

In retrospect CURR may have been a better name for the HEAD symref
but its far too late to even consider changing that, so lets not
go down that road.  :-)

-- 
Shawn.
-

From: Johannes Schindelin
Date: Thursday, November 16, 2006 - 3:21 pm

Hi,


This is actually a perfect example for

- a script that is porcelain as well as plumbing (you are supposed to use 
it directly, or via pull), and for

- a terrible UI.

_If_ you use git-fetch directly you virtually always want to store the 
result. I was tempted quite often to submit a patch which adds a command 
line switch --no-warn, which is passed to git-fetch by git-pull, and 
without which git-fetch complains if the branch-to-be-fetched is not 
stored right away (and refuses to go along).

_Also_, git-pull not storing the fetched branches at least temporarily 
often annoyed me: the pull did not work, and the SHA1 was so far away I 
could not even scroll to it. The result: I had to pull (and fetch!) the 
whole darned objects again. Again, I was tempted quite often to submit a 
patch which makes git-pull fetch the branches into refs/fetch-temp/* and 
only throw them away when the merge succeeded.

Ciao,
Dscho

-

From: Junio C Hamano
Date: Thursday, November 16, 2006 - 3:44 pm

I think the earlier write-up by Linus on magic HEADs would help
documenting FETCH_HEAD better.

-

From: Johannes Schindelin
Date: Thursday, November 16, 2006 - 5:29 pm

Hi,


I am not sure that documenting FETCH_HEAD better would help. As Han-Wen 
pointed out (and some colleagues of mine who would never subscribe to a 
mailing list), people do not read the manual, but rather try to wrap their 
heads around the inner workings from the interface. And FETCH_HEAD just 
does not meet _any_ expectation a sane (read: untainted) user might have.

While I'm at it: the problem I pointed out with -pull may annoy just me.

But there is another problem with "git fetch": a common work flow is 
tracking other peoples branches. And since git makes it so easy to 
have multiple branches, chances are that you track more than one 
branch per remote repository.

Now, an old gripe of mine was the lack of "git fetch --all". I wrote a 
script for that (Linus would be proud of me!), which just does "git 
ls-remote" and constructs a command line for "git fetch" from that.

But even if you agree with the common story that you should specify the 
branches you want to track: it is hard!

If I were new to git, after reading some tutorials I would _expect_ "git 
fetch" to be the tool to track branches. (I posted a patch to at least be 
able to store the current "git fetch" command line under a nick IIRC). But 
it does not.

(Of course, after reading several documentation, as a new user I would 
eventually find that I should edit .git/remotes/<nick>, or even 
edit/-repo-config the remotes information in the config, but I would fully 
expect a new user to give up before reaching that stage.)

But maybe I got it all wrong and this is not the common expectation...

Ciao,
Dscho

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 3:49 pm

Again, why didn't you use FETCH_HEAD?

If the user doesn't give us a head to write to, we clearly MUST NOT write 
to any long-term branch. That would be a _horrible_ mistake. 

So all your complaints seem totally misplaced. The UI is both usable and 
practical, and your complaint that git pull doesn't store the fetched 
branches is just NOT TRUE.

And your "solution" is obviously totally unusable. git ABSOLUTELY MUST NOT 
overwrite any existing branches unless explicitly told to do so by the 
user.

So I really don't see your point. 

A lot of the complaints seem to not be about the interfaces, but about 
people not _understanding_ and knowing what the interfaces do. If you were 
confused about something (like not realizing that FETCH_HEAD is there and 
very much usable), how about sending in a patch to make FETCH_HEAD use 
clearer in whatever docs you looked at and didn't find it mentioned in.

Now, there is no question that some of the interfaces can get a bit 
"interesting" to use. For example, if you really don't want to re-fetch 
for some reason, FETCH_HEAD actually does contain enough information that 
you should be able to just re-do a failed merge, for example, including 
the message generation. But at that point it really _does_ get a bit 
complicated, and you end up doing something like

	git merge "$(git fmt-merge-msg < .git/FETCH_HEAD)" HEAD FETCH_HEAD

which should _work_, but I'm not going to claim that it's all that easy to 
understand.

(That said, read that one-liner a few times, and suddenly it doesn't seem 
_that_ complicated any more, now does it? You can probably even guess what 
it's really going to do, even if you don't know git all that well. It's 
not unreadable line noise, is it?)

Of course, if I had a merge that failed (the most common reason being that 
I had some uncommitted patch in a file that wanted to be updated by the 
merge), I'd never actually do the above one-liner. I'd just re-do the 
pull. But if networking was _really_ ...
From: Linus Torvalds
Date: Thursday, November 16, 2006 - 4:08 pm

Btw, I'd like to claim that this is a _great_ user interface.

Yeah, it's different from other SCM's. I don't think you'd really want to 
script a merge like this in CVS, especially not using standard UNIX 
pipelines etc. But it's an example of how a lot of git operations - even 
the "high level ones" are pretty scriptable, using very basic and very 
simple standard UNIX shell scripting.

So even though I'd not actually _do_ the above one-liner, I think it's a 
great example of how git really works, and how scriptable it can be, 
without a lot of huge problems.

So considering that "FETCH_HEAD" works pretty much everywhere, and that 
you can also use the totally non-scripting approach of doing "standard" 
SCM things like

	git diff ..FETCH_HEAD

or 

	gitk HEAD...FETCH_HEAD

to look at what got fetched (and in the latter case look at both the 
current HEAD _and_ FETCH_HEAD, and what was in one but not the other), I 
really think it's unfair to say that "git fetch" does not have a nice UI.

It's just that "git fetch" can be used two totally different ways:

 - "git fetch" to get something temporary: use FETCH_HEAD, and do _not_ 
   specify a destination branch

 - "git fetch" as a way to update the branches you already have, by either 
   using explicit branch specifiers (which would be unusual, but works), 
   or by just having the branch relationships listed in your .git/remotes/ 
   file or .git/config file.

both are actually very natural things to do.

What is probably _not_ that natural is to do the explicit branch 
specifier, ie

	git fetch somerepo remotebranch:localbranch

which obviously works, but you wouldn't want to actually do this very 
often. Either you do something once (and use FETCH_HEAD, which is actually 
nicer than a real branch in some respects: it also tells you were you 
fetched _from_, and it can contain data on merging from _multiple_ 
branches), or you set up a "real translation" in your configuration files.

So I would say that ...
From: Johannes Schindelin
Date: Thursday, November 16, 2006 - 4:36 pm

Hi,


It is a terrible UI, because it was not that obvious to me. And I consider 
myself not a git newbie.

Besides, it is not really a temporary branch. If it was, the pull would 


I was _not_ suggesting a long-term branch. Just a way to do-what-i-want 

Guess three times why I did not post the patches.

But the real problem is not necessarily the behaviour; it is the obscure 
fashion of the behaviour. You may not understand that problem, because you 
were there from the beginning. You saw the big-bang and how all the 
quarks formed all of a sudden, and how matter and eventually planets 
and suns came into being.

But others (me included) were not there. Or they did not really watch. And 
now they see all these creatures, and plants, and bacteria, and they do 
not understand how these are all connected, because of that. And now they 
think "wow that must have been some intelligent design, and really a 
miracle, and I cannot understand how it works." But that is not true 
(the latter part of course).

There is something to be said about the simplicity of Mercurial. It's 
inner workings may suck, but people get easily attracted by it.

I do not claim we should imitate Mercurial, or even hide the index (even 
if I sometimes wonder if the index is not just a clever way to accelerate 

But the interfaces should be usable interfaces! They should _explain_ what 

I find that quite easy to understand. Why? Because I happen to _know_ the 
syntax of -merge and -fmt-merge-msg. For similar reasons I _understand_ 
why -pull behaves like it does. But others don't; they will shudder and 
then run.

Maybe it is not important that -pull fetches all objects all over again. 
But it _is_ important to make things like merging branches (local or 
remote) trivial. It _is_ important to make the user experience be fun.

Ciao,
Dscho

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 5:49 pm

Heh. The "temporary branches" are actually the _original_ branches as far 
as git is concerned. The long-term branches only came later.

So in many ways, HEAD, FETCH_HEAD, MERGE_HEAD and ORIG_HEAD are more 
fundamental than any long-term branch has ever been, and maybe they should 
be taught first as such.

So you're newbie enough that you've only seen those new-fangled "real" 
branches.

When I was young, we had to walk to school up-hill in three feet of snow 

Well, exactly because they are temporary, we can't actually trust the 
objects they point to. They have no "real" long-term life, so no, I'm 
afraid that we always will have to re-fetch the objects, because fetching 
them is the only way to know that we still have them. 

That said, we could certainly _make_ them be honored by things like "git 
prune" and friends. But yes, they really _are_ temporary branches right 
now, and part of the meaning of that "temporary" is exactly the fact that 
git fetch will not trust that you still have the objects. 

For example, if you used one of the old-fashioned commit walkers, maybe we 
got the initial commit, but we may not have gotten the whole _chain_. See?


Well, we clearly should document them better. Anybody?

		Linus
-

From: Carl Worth
Date: Thursday, November 16, 2006 - 6:08 pm

Older in git's history as it developed is not a good match for more

I for one am totally unsatisfied with this approach.

Here's an operations I'd like to be able to do:

	Given a (URL, branch) pair I'd like I'd like to be able to
	investigate that code, (say with the fancy new "read-only
	branch" concept we've been talking about).

What are my options for this operation? What might a new user's
reaction to them be?

a) git fetch URL branch
   git checkout FETCH_HEAD

   This is really ugly. A name like "FETCH_HEAD" is something a user
   should really never have to type. It's hideously hard to type and
   has no natural discoverability. Yuck, yuck, yuck.

b) vi .git/remotes/something
   git fetch something
   git checkout branch

   Also yuck. I hope it's obvious that having to edit a configuration
   for this simple operation is a non-starter.

c) git fetch URL branch:local-branch
   git checkout local-branch

   We're getting close to the desired functionality now, but the UI
   makes users cringe? "What's that : for?" Why do I need another
   name?" etc. Linus, you yourself said this is a form that users
   should generally avoid.

d) git fetch URL branch:branch
   git checkout branch

   One step closer. But there's still that goofy extra ':' and a
   doubled name in the first command. "Why is that there? Git sure is
   weird...".

What I think this operation should look like is:

	git fetch URL branch
	git checkout branch

And the fetch should just complain if there's a name clash. Or better,
the fetch should tuck the fetched branch into its own URL-specific
namespace and then the checkout command can kindly prompt if there is
any ambiguity:

	Which "branch" do you want?
		local/branch
		remote-url/branch

or whatever.

See? That's what reasonable UI should look like.

Please feel free to keep using vestiges like FETCH_HEAD as much as you
like, but please don't recommend documenting them better as a solution
for UI warts in git. (If you ...
From: Johannes Schindelin
Date: Thursday, November 16, 2006 - 6:22 pm

Hi,


Nonono.

We made _sure_ that FETCH_HEAD is only written once _all_ the objects were 
received. So, actually, we _can_, and we _should_ trust the objects they 
point to!


Huh? I am quite certain that FETCH_HEAD is not updated in that case. If it 
is, that's a bug.

Ciao,
Dscho
-

From: Petr Baudis
Date: Thursday, November 16, 2006 - 6:52 pm

It may be updated and then things may break _afterwards_. git-prune will
happily blow anything referenced by FETCH_HEAD, it's not considered by
the fsck-objects reachability analysis.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
-

From: Johannes Schindelin
Date: Thursday, November 16, 2006 - 7:16 pm

Hi,


This actually underlines my point: FETCH_HEAD is no _real_ branch, not 
even a temporary one. If it was, git-prune would not lose the related 
objects.

Ciao,
Dscho

-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 4:40 pm

From the point of view of a user, there is not really a difference
between the two.  As a user, you form a mental model of how things
work by looking at the interface. If the interface is bad, the user
creates a faulty model in his head, and starts doing things that
are perfectly logical in the faulty model, but stupid and silly when
you consider the actual internals.

A nice book about this is "The Design of Everyday Things" by Donald
Norman.

-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 4:32 pm

What happens on savannah is that the sysadmins set up an empty GIT
repo with access, and leave it to you to push the stuff.  Of course,

Perhaps ; from a UI viewpoint, it would be nice though, even if it
were aliased to a simple push. (Darcs has a get command analogous to

No, I don't understand. In the fetch all the objects with their SHA1s
were already downloaded. I'd expect that the fetch with a refspec
would simply write a HEAD and a refs/heads/master, and notice that all
the actual data was already downloaded, and doesn't download it again. 


-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 10:57 am

Here's a very lightly tested patch that allows you to use "git pull" to 
populate an empty repository.

I'm not at all sure this is necessarily the nicest way to do it, but it's 
fairly straightforward.

Junio, what do you think?

		Linus

---
diff --git a/git-pull.sh b/git-pull.sh
index ed04e7d..7e5cee2 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -44,10 +44,10 @@ do
 	shift
 done
 
-orig_head=$(git-rev-parse --verify HEAD) || die "Pulling into a black hole?"
+orig_head=$(git-rev-parse --verify HEAD 2> /dev/null)
 git-fetch --update-head-ok --reflog-action=pull "$@" || exit 1
 
-curr_head=$(git-rev-parse --verify HEAD)
+curr_head=$(git-rev-parse --verify HEAD 2> /dev/null)
 if test "$curr_head" != "$orig_head"
 then
 	# The fetch involved updating the current branch.
@@ -80,6 +80,11 @@ case "$merge_head" in
 	exit 0
 	;;
 ?*' '?*)
+	if test -z "$orig_head"
+	then
+		echo >&2 "Cannot merge multiple branches into empty head"
+		exit 1
+	fi
 	var=`git-repo-config --get pull.octopus`
 	if test -n "$var"
 	then
@@ -95,6 +100,12 @@ case "$merge_head" in
 	;;
 esac
 
+if test -z "$orig_head"
+then
+	git-update-ref -m "initial pull" HEAD $merge_head "" || exit 1
+	exit
+fi
+
 case "$strategy_args" in
 '')
 	strategy_args=$strategy_default_args
-

From: Junio C Hamano
Date: Thursday, November 16, 2006 - 11:27 am

Yeah, I talked about making "merge" treat missing HEAD as a
special case of fast forward, but I like yours better.  It is a
lot cleaner and to the point.

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 11:28 am

So this is the place that probably wants a "git-checkout" before the 
exit, otherwise you'd (illogically) have to do it by hand for that 
particular case.

Of course, we should _not_ do it if the "--bare" flag has been set, so you 
migth want to tweak the exact logic here.

		Linus
-

From: Junio C Hamano
Date: Thursday, November 16, 2006 - 12:47 pm

As you said, pull inherently involve a merge which implies the
existence of associated working tree, so I do not think there is
any room for --bare to get in the picture.  We already do the
checkout when we recover from a fetch that is used incorrectly
and updated the current branch head underneath us.

To give the list a summary of the discussion so far, here is a
consolidated patch.

-- >8 --
From: Linus Torvalds <torvalds@osdl.org>
Subject: git-pull: allow pulling into an empty repository

We used to complain that we cannot merge anything we fetched
with a local branch that does not exist yet.  Just treat the
case as a natural extension of fast forwarding and make the
local branch'es tip point at the same commit we just fetched.
After all an empty repository without an initial commit is an
ancestor of any commit.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---
diff --git a/git-pull.sh b/git-pull.sh
index ed04e7d..e23beb6 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -44,10 +44,10 @@ do
 	shift
 done
 
-orig_head=$(git-rev-parse --verify HEAD) || die "Pulling into a black hole?"
+orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
 git-fetch --update-head-ok --reflog-action=pull "$@" || exit 1
 
-curr_head=$(git-rev-parse --verify HEAD)
+curr_head=$(git-rev-parse --verify HEAD 2>/dev/null)
 if test "$curr_head" != "$orig_head"
 then
 	# The fetch involved updating the current branch.
@@ -80,6 +80,11 @@ case "$merge_head" in
 	exit 0
 	;;
 ?*' '?*)
+	if test -z "$orig_head"
+	then
+		echo >&2 "Cannot merge multiple branches into empty head"
+		exit 1
+	fi
 	var=`git-repo-config --get pull.octopus`
 	if test -n "$var"
 	then
@@ -95,6 +100,13 @@ case "$merge_head" in
 	;;
 esac
 
+if test -z "$orig_head"
+then
+	git-update-ref -m "initial pull" HEAD $merge_head "" &&
+	git-read-tree --reset -u HEAD || exit 1
+	exit
+fi
+
 case "$strategy_args" in
 '')
 	strategy_args=$strategy_default_args

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 12:53 pm

Fair enough. Feel free to add the signed-off-by from me too, 

		Linus
-

From: Carl Worth
Date: Thursday, November 16, 2006 - 11:13 am

For that we'd also need a way for clone to be able to fetch just a
single branch, and not all of them as well.

There is some clone vs. fetch asymmetry here that has annoyed me for a
while, and that I don't think has been mentioned in this thread
yet. Namely:

clone: can only be executed once, fetches all branches, "remembers"
       URLs for later simplified use

fetch: can be executed many times, fetches only named branches,
       doesn't remember anything for later

I've often been in the situation where I cloned a long time ago, but
I'd like to be able to fetch everything that I would get if I were to
start a fresh clone.

-Carl
From: Johannes Schindelin
Date: Thursday, November 16, 2006 - 4:00 pm

Hi,


Never ever underestimate pet peeves. If we give many people an obvious 
reason (however trivial and bike-shed-coloured) to complain, they will 
complain.

If we pull (pun intended) that reason away under their collective 
backsides, they will have to find another reason to complain. But by the 
time they found something, they will already be happy git users!

But since you just provided a patch to make life easier on non-gitters, I 
guess you agree with that already.

And hopefully you also agree that enhancing the syntax of git-merge to 
grok "git-merge [-m message] <branch>" and "git-merge [-m message] 
<url-or-remote> <branch>" would be a lovely thing, luring even more 
people into using git.

Maybe they even start complaining about subversion and CVS calling a merge 
"update", who knows?

Ciao,
Dscho

-

From: Linus Torvalds
Date: Thursday, November 16, 2006 - 4:22 pm

I do actually think that this discussion has been informative, partly 
because I never even realized that some people would ever think to do 
"init-db" + "pull". 

Making things like that work is easy enough, it's just that I never saw 
any point until people complained. And when they complained, the initial 
complaint wasn't actually obvious. Only when Han-Wen actually gave 
something that didn't work, was it clear that the real issue wasn't so 

I definitely think we can make "git merge" have a more pleasant syntax. 
I'm just still not sure that people should actually use it ;)

My real point was/is that usually it's really not the "naming details" 
that people _really_ have problems with. The real problems tend to be in 
learning a new workflow.

We can make some of those workflows easier, but I would heartily recommend 
that people not worry about naming of "pull" vs "fetch", because that's 
almost certainly not really the issue. Instead, if you have a problem, 
rather than concentrating on the names of the programs, say:

 - what do you want to get done.

   Most likely it's _trivial_ to do with git, it's just that somebody used 
   the wrong approach, and then it didn't work at all.

 - give actual examples of a workflow that didn't work or was complex.

   (again, the "init-db" + "pull" example). 

   And yes, in many cases, it might well be a case of "sure, we can make 
   that _other_ workflow work too". But somebody like me, who has used git 
   for a year and a half, and used BK before it, probably simply uses a 
   different workflow than somebody who comes from CVS. 

For example, I suspect that your gripe with "git fetch" was just from 
using it in a really awkward manner. Maybe we could make your workflow 
work with git too, but maybe it really already (and always) did, you just 
used a particular tool in a way that made the use be really really 
painful.

Sometimes it's just a question of "ok, use it like _this_, and now it's 
actually really ...
From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 5:05 pm

I agree that discussions on naming may cloud the issue, but "learning
the workflow" implies that people should adapt to the limitations of
their tools.  That's only a viable stance when the tools are finished
and completely perfect.

Until that time, it would be good goal to remove all idiosyncrasies,
all gratuitious asymetries and needless limitations in the commands of
git, eg.

 - clone but not a put-clone,

 - pull = merge + fetch, but no command for merge + throw

 - clone for getting all branches of a repo, but no command for
   updating all branches of a repo.  

Of course, when all warts are fixed, backward compatibility will force
us to choose some new names. At that point, a discussion on naming is
in place.


-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

-

From: Junio C Hamano
Date: Thursday, November 16, 2006 - 5:13 pm

This one I can understand, but how would you propose to "update
all branches", in other words what's your design for mapping
remote branch names to local branch namespaces?

It would be nice if the design does not straightjacket different
repository layouts different people seem to like, but I think it
would be Ok to limit ourselves only to support the straight
one-to-one mapping and support only separate-remote layout.

-

From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 5:27 pm

put clone would be the putative inverse of clone, ie. make a clone of

throw is the hypothetical opposite of fetch. I agree that this is
academical, because it's logical to only allow fast-forwards for

I think the whole clone design is a bit broken, in that the "master"
branch gets renamed or copied to "origin", but all of the other
branches remain unchanged in their names.

It's more logical for clone to either

 * leave all names unchanged

 * put all remote branches into a subdirectory.  This would also make
   it easier to track branches from multiple servers.

   At present,  I have in my build-daemon the following branches,

	cvs-head-repo.or.cz-lilypond.git
	hanwen-repo.or.cz-lilypond.git
	hwn-jcn-repo.or.cz-lilypond.git
	lilypond_1_0-repo.or.cz-lilypond.git
	lilypond_1_2-repo.or.cz-lilypond.git
	lilypond_1_4-repo.or.cz-lilypond.git
	lilypond_1_6-repo.or.cz-lilypond.git
	lilypond_1_8-repo.or.cz-lilypond.git
	lilypond_2_0-repo.or.cz-lilypond.git
	lilypond_2_2-repo.or.cz-lilypond.git
	lilypond_2_3_2b-repo.or.cz-lilypond.git
	lilypond_2_3_5b-repo.or.cz-lilypond.git
	lilypond_2_4-repo.or.cz-lilypond.git
	lilypond_2_6-repo.or.cz-lilypond.git
	lilypond_2_8-repo.or.cz-lilypond.git
	master-git.sv.gnu.org-lilypond.git
	master-hanwen
	master-repo.or.cz-lilypond.git
	origin-repo.or.cz-lilypond.git
	stable
	stable-2.10
	stable--2.10-git.sv.gnu.org-lilypond.git

  It would solve lots of problems for me if cloning and fetching would
  put branches into a subdirectory, ie.

    git clone git://repo.or.cz/lilypond.git

  leads to branches

    repo.or.cz/lilypond_2_8
    repo.or.cz/lilypond_2_6
    repo.or.cz/lilypond_2_4
    repo.or.cz/master
     (etc..)

	
-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Petr Baudis
Date: Thursday, November 16, 2006 - 5:35 pm

So effectively to tell git push not to unpack on the remote side, and to
push all branches and relevant tags.


That's basically exactly what git clone --use-separate-remote should do.
Now only if it would become the default... :-)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
-

From: Carl Worth
Date: Thursday, November 16, 2006 - 5:37 pm

As long as its consistent with "clone" I'll be happy, (I think as part
of a separate topic we need to fix the mappings in clone, see
--use-separate-remotes as default and related).

The current case is really annoying where I have to throw use clone
into a new repository just to get everything, rather than just being
able to fetch everything into the repository I already have.

-Carl
From: Carl Worth
Date: Thursday, November 16, 2006 - 6:25 pm

What I want here is a command "git update" that fetches and
fast-forwards the all branches which are designated as "tracking" a
branch in some known remote repository. And git-clone would setup all
branches appropriately so that they would be updated by git-update.

Additionally, it would be nice if git-update would also create new
tracking branches for all remotes repositories that had been
designated as being tracked, (and git-clone would do this as well).

There should also be a mechanism to easily create new tracking support
for specific branches or all branches of a repository, (could be "git
fetch URL branch" or "git fetch --all URL", for example).

With this kind of setup, I would use "git update" regularly, and only
ever merge locally. And by definition merging with any local tracking
branch would have just as much information available as "pull URL
branch" so the message would be the same.

I've been using git for 10-11 months, so I think I understand the
models fairly well, and I'd be really happy with a setup like that. I
also have talked with a fair number of (non-git-using) users who think
git is confusing, but I think would find the above scenario just fine.

In this scenario, git pull would still work just fine, but it would
also be much easy to teach a workflow that didn't use pull at all, so
if there's any git-pull confusion that's an actual problem, it could
be avoided.

Junio, what do you think of a setup something like that? I really
don't want to create a command other than "git" to implement it.

-Carl
From: Linus Torvalds
Date: Thursday, November 16, 2006 - 5:39 pm

As mentioned, in order to "put-clone", you generally have to "create" 
first, so the "put-clone" really makes no sense.

The _true_ reverse is really your

 - "git init-db" on both sides

 - "git pull" (your workflow ;) on receiving

 - "git push" on sending.

The fact that we can do "git clone" on the _receiving_ side is an 
assymmetry, but it's not gratutous: when receiving we don't need any extra 
permissions or setup to create a new archive. In contrast, when sending, 

Again, this is not gratuitous, and the reason is very similar: when you 
pull, you're pulling into something that _you_ control and _you_ have 
access to, namely your working directory. In order to merge you have to 
have the ability to fix up conflicts (whether automatically or manually), 
and this is something that you _fundamentally_ can only do when you own 
the repo space.

Again, when you do "push", the reason you can't merge is not a "gratuitous 
assymmetry", but a _fundamental_ assymmetry: by definition, you're pushing 
to a _remote_ thing, and as such you can't merge, because you can't fix up 
any merge problems.

See?

In many ways, if you want _symmetry_, you need to make sure that the 
_cases_ are symmetrical. If you have ssh shell access, you can often do 
that, and the "reverse" of a "git pull" is actually just another "git 
pull" from the other side:

	ssh other-side "cd repo ; git pull back"

Now they really _are_ symmetrical: "git pull" is really in many ways ITS 
OWN reverse operation. 

But "push" and "pull" _fundamentally_ aren't symmetric operations, and you 
simply cannot possibly make them symmetric. Any system that tries would be 
absolutely horrible to use, exactly because it would be either:

 - making local/remote operations totally equivalent

   This sounds like a "good" thing, but from a real user perspective it's 
   actually horribly horribly bad. Knowing the difference between local 
   and remote is what allows a lot of performance optimizations, and a ...
From: Han-Wen Nienhuys
Date: Thursday, November 16, 2006 - 5:52 pm

Point taken;  thank you. 

In that case, we're full circle with the command naming issues. Push
and pull are fundamentally asymmetric operations, but then a
consistent UI would dictate that they wouldn't be named symmetrically,
as they are now.


-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
-

From: Michael K. Edwards
Date: Thursday, November 16, 2006 - 6:34 pm

I think there's a fundamental assumption built into the design of git
that most programmers accustomed to a corporate environment don't
understand.  Namely, that each programmer owns his or her entire
"repository", and can do whatever he or she darn well pleases with it
at any time.  Go ahead and create hundreds of transient branches as
part of a scripted "merge complexity metric" calculation.  Try three
different refactoring strategies on different branches, abandon two of
them, and prune them months later.  And generally use the power of the
SCM to juggle a lot of things at once, because there's no sysadmin
gatekeeper stopping you, and the thing is designed and coded scalably
so it doesn't grind to a halt as soon as everyone has dozens of
private branches.

Even if you do find a way to push git in a direction that it doesn't
scale, it's no one's problem but your own -- people who pull from you
are pulling the _content_ on the branches they care about, not the
structure of your repository.


One person's gratuitous asymmetry is another's minimalism.  (If the
symmetric thing doesn't make any sense or can't be implemented
scalably, leave it out.)  It is more important that git continue to


pull = fetch + merge.  It is (almost?) always followed by a judgment
call based on the merge results.  merge + throw doesn't make any sense
in terms of the job at hand, which is facilitating human judgments

clone is shorthand for the steps involved in setting up a new
repository with content similar to an existing one.  There isn't any
merge involved, and no scope for human judgment, so it's simplest to
clone the whole state of the remote repository (including tags and
branches) and let the user blow away any branches he doesn't need.
But once the clone is done, all of those branches are _truly_ _local_
-- they don't retain any reference to the remote branches, and you can
commit to all of them.  The only entry placed in .git/remotes is the
"origin" of the new clone, which is the ...
From: Michael K. Edwards
Date: Thursday, November 16, 2006 - 11:42 pm

Actually, this "origin" entry does contain "Pull:" lines for all of
the branches that were cloned, so that "git pull" fetches and merges
updates to all of these branches.  (If upstream is in the habit of
reverting things, you may need "git pull -f"; I just did that on the
git repo to handle a failure to fast-forward on the "pu" branch.)

Presumably "git branch -D" should inspect everything under
.git/remotes to see whether one or more Pull: lines need to be deleted
along with the branch.  Currently, it looks like "remotes" entries are
created only by "git clone" or by hand.  Junio, are there any plans to
manage the contents of "remotes" through the tool instead of by hand?

Cheers,
- Michael
-

From: Junio C Hamano
Date: Friday, November 17, 2006 - 12:32 am

I am not sure what you mean.  .git/remotes files do not describe
any relationship between local branches (and that is where one
of the problem raised in recent thread -- pull does not notice
on which branch you are on and change its behaviour depending on
it), so I do not think there is anything gained for "git branch

I muttered something in a near-by thread

	Message-ID: <7vr6w78b4x.fsf@assigned-by-dhcp.cox.net>

I am reasonably sure a separate tool (what I tentatively called
"maint-remote" in the message) is necessary, because, while it
would be relatively easy to make "git fetch" and friends to add
new mappings in the default way under a new option, people with
different workflows would want differnt "default mappings", and
adding new mappings for _all_ remote branches is useful only for
people who work in one particular way (namely, the CVS-style
"the central distribution point is where everybody meet" model).

The tool, under "interactive" mode, would probably take one
parameter, the short name of a remote ($name), and would give
you a form to update its URL:, shows ls-remote output against
that repository and would let you:

 - update the URL: which would probably cause the ls-remote to
   be re-run;

 - remove existing mappings;

 - add mappings for a remote branch for which you do not have a
   corresponding tracking branch, with a straightforward default
   mapping:

   	refs/heads/$branch:refs/remotes/$name/$branch

But I haven't thought things through yet.


-

From: Michael K. Edwards
Date: Friday, November 17, 2006 - 6:24 pm

.git/remotes/foo does contain Pull: lines which indicate the local
branch onto which to _fetch_ remote changes.  It's the subsequent
_merge_ that doesn't notice which branch you have checked out.

Cheers,
- Michael
-

From: Horst H. von Brand
Date: Wednesday, November 22, 2006 - 7:52 pm

Han-Wen Nienhuys <hanwen@xs4all.nl> wrote:



throw + merge (at the remote end, that is)?
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                    Fono: +56 32 2654431
Universidad Tecnica Federico Santa Maria             +56 32 2654239
Casilla 110-V, Valparaiso, Chile               Fax:  +56 32 2797513
-

From: Theodore Tso
Date: Wednesday, November 15, 2006 - 6:14 pm

Yes, "bk pull" had an implied merge.  But, the reason why bk pull was
never really a problem with Bitkeeper is because it didn't really have
support for multiple branches active within the same repository ---
what Larry called "lines of development".  Or rather, Larry started
down the path of implementing lines of development, and then never
fully supported it, mainly because making it easy for people to use
was the tricky part.   

So with Bitkeeper, with "bk pull" there was never any question about
which branch ("line of development") you would be merging into after
doing a "bk pull", since there was only one LOD, and given that BK had
the rule that a within a LOD only one tip was allowed, a "bk pull"
_had_ to do do a merge operation.   

The moment you start supporting multiple unmerged tips in a repository
i.e., branches, it raises the question, "which branch should the pull
operation merge onto"?  And git's answer, "the current branch", is
often not the right one.  *That's* why always doing a merge isn't
always the right answer, and so in the git world, people are told, use
"git fetch" instead, and in the hg world, "hg pull" doesn't do the
merge.  IMO, it's a fundamental result of the fact that both git and
hg have chosen to support mulitple LOD's, whereas BK punted on the
concept.

If you are operating on your local development branch, the reality is
that merging is probably not the right answer in the general case,
which is why the hg world have omitted doing the merge.  And by
telling people, use "git fetch" instead, that's also an implicit
admission that merging onto the current branch is often not the Right
Thing.

The problem is that "pull" is a very evocative word, especially given
the existence "push", and so in the git world we are reduced to
telling people, "you really don't want to use pull, trust me".  

Is this a major issue?  Not really; I can think of a number of other
issues that make git hard to learn, and why hg has a more gentle
learning curve, ...
From: Junio C Hamano
Date: Wednesday, November 15, 2006 - 9:21 pm

I agree, but I wonder why you are pulling/fetching (with or
without merge) if you are operating on your local development

I would rather say "use 'git branch' to make sure if you are

I have to disagree with this.  In the simplest CVS-like central
repository with single branch setup in which many "novice users"
start out with, there is almost no need for "git fetch" nor
tracking branch.  You pull, resolve conflicts, attempt to push
back, perhaps gets "oh, no fast forward somebody pushed first",
pull again, then push back.  So I am not sure where "you really
do not want to use pull.  trust me" comes from.

It is a different story for people who _know_ git enough to know
what is going on.  They may be using multiple branches and
interacting with multiple remote branches, and there are times
you would want fetch and there are other times you would want
pull.  But for them, I do think the suggestion would never end
with "trust me" -- they would understand what the differences
are.




-

From: Alexandre Julliard
Date: Thursday, November 16, 2006 - 4:34 am

We do that for Wine. The problem is that we recommend using git-rebase
to make it easier for occasional developers to keep a clean history,
and rebase and pull interfere badly.

The result is that we recommend always using fetch+rebase to keep up
to date, but this is confusing many people too, because git-fetch
appears to do a lot of work yet leaves the working tree completely
unchanged, and git-rebase doesn't do anything (since in most cases
they don't have commits to rebase) but has an apparently magical
side-effect of updating the working tree.

Ideally it should be possible to have git-rebase do the right thing
even if the branch has been merged into; then we could tell people to
always use git-pull, and when they get confused by seeing merges in
their history have them do a git-rebase to clean things up.

-- 
Alexandre Julliard
julliard@winehq.org
-

From: Petr Baudis
Date: Thursday, November 16, 2006 - 7:01 am

How do those developers submit their changes? Do they push? If they do,
git-rebase can be saving one merge at most, and the merge is actually a
good thing (someone should write some nice standalone writeup about
that).

If they don't have push access and maintain their patches locally until
they get accepted, perhaps it would be far simpler for them to use
StGIT?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
-

From: Alexandre Julliard
Date: Thursday, November 16, 2006 - 8:48 am

For regular developers, sure. But regular developers will need to
properly understand the git model anyway, and then they will able to
make sense even of the standard git commands ;-)  The problem is that
there isn't a smooth progression to that point.

At first, a user will simply want to download and build the code, and
for that git-pull works great, it's a one-stop command to update their
tree.

Then after a while the user will fix a bug here and there, and at that
point git-rebase is IMO the best tool, it's reasonably easy to use,
doesn't require learning other commands, and once the patch is
accepted upstream it nicely gets the tree back to the state that the
user is familiar with.

The problem is that rebase doesn't work with pull, so the user needs
to un-learn git-pull and start using git-fetch; it's to avoid this
that we recommend using git-fetch from the start, which is unfortunate
since it makes things harder for beginners.

-- 
Alexandre Julliard
julliard@winehq.org
-

From: Theodore Tso
Date: Thursday, November 16, 2006 - 9:07 am

Well, when I was using BitKeeper, I never would.  Bitkeeper has what
Linus calls the broken "repository == branch" model.  So normally I
would have one repository where I would track the upstream branch, and
only do bk pull into that branch.  I would do my hacking in another
repository (i.e., branch), and periodically keep track wha was going
on in mainline by cd'ing to the mainline repository and doing the bk
pull there.  

The challenge when you put multiple branches into a single repository,
is you have to keep track of which branch you happen to be in.  In the
BK world, this was obvious because it would show up in my shell
prompt:

<tytso@candygram>       {/usr/src/linux-2.6}
2% 

(OK, obviously I'm in the Linux 2.6 upstream repository)

In a system where you need to keep track of what branch you are in via
an SCM-specific local state information, it's easy to get confused and
do a pull when you are in the "wrong" branch, or while you have local
state in your working directory.   

What I currently do (and I'm sure I'm being really horrible and need
to be say 100 "Hail, Linus"'es for penance for not adhering staying in
the one true distributed state of grace) is that I keep an entirely
separate Linux 2.6 git repository just to make sure I never get
confused about what branch I might happen to be in when I do the "git
pull" --- and yeah, I could have used "git fetch", but 3+ years of BK
usage plus Hg usage is hard to get away from.  I'm sure this is where
Linus would say that use of BK and Hg, causes permanent brain damage,
ala's Dijkstra's ofted quoted comment about use of Basic inducing

I think the problem is the people who have had years of BK or Hg
experience.  Maybe it's more of a documentation problem; perhaps a
"git for BK" or "git for Hg" users is what's needed.  The problem
though is that while use of BK is definitely legacy, there are going

Well, I think this is where git's learning curve challenges are.  Yes,
for users that are doing the stupidest, most ...
From: Theodore Tso
Date: Thursday, November 16, 2006 - 9:49 am

Err, what I meant to say is that there are going to be a lot of people
who will need to simultaneously use both git and Hg.

						- Ted
-

From: Sanjoy Mahajan
Date: Wednesday, November 22, 2006 - 4:21 pm

As a 80%-hg/20%-git user, I'm curious what features of git you had in
mind, so I know where to look as I wander up the git learning curve.

My experience with the git user interface, for what it's worth, is
that I never quite get the conceptual model crystal clear enough in my
head. So it won't stay for long enough for me to progress up the
learning curve and retain the gains.  I move up a bit, but the gain
soon evaporates and I backslide, and then just hack my way through it.

I found hg's conceptual model very easy to learn, almost as if I don't
have to remember anything.  Maybe that simplicity comes at a price,
whence my question at the start about the extreme-power features of
git.

-Sanjoy

`Never underestimate the evil of which men of power are capable.'
         --Bertrand Russell, _War Crimes in Vietnam_, chapter 1.
-

From: Petr Baudis
Date: Wednesday, November 15, 2006 - 9:30 pm

I would agree that having "pull" mean something different in Cogito
than in Git was a bad idea (explanation: historically, for some period
of time Cogito had cg-pull which meant the same as cg-fetch or hg pull;
later it got renamed to cg-fetch). But I'm also happy that Cogito just
does not use the "pull" expression at all currently: "updating" seems to
be a clear and unloaded enough concept for new people. Pull is really
_very_ confusing, with it meaning something different (but not different
enough) in _all_ other systems but BK (which is basically irrelevant
nowadays).

  That said, I agree with your argument that changing it in Git now
might just result in more confusion. I'm just trying to explain Cogito's
choice here, and I believe it does no good nor harm to Core Git if it
just uses different name for the concept and avoids the original name at
all (except explaining in the docs that updating in Cogito is what
pulling is in Git).

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
-

From: Petr Baudis
Date: Wednesday, November 15, 2006 - 1:12 pm

How was/is fetch contaminated?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
-

From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 1:26 pm

I think "fetch" is sane.  Its only problem is a missing symetrical 
counterpart verb, like "get" and "put".


Nicolas
-

From: Linus Torvalds
Date: Wednesday, November 15, 2006 - 1:50 pm

If you're a dog owner, the obvious counterpart for "fetch" is "throw" ;)

I think "get" and "put" would be bad, just because of confusion with 
"sccs get" (ie it has that "get this file" connotations).

Maybe "fetch" and "push" aren't totally diametrically opposite, but 
really, I don't think they are that hard to understand either. We do have 
the BK legacy of "pull" implying a merge, and that's fairly fundamental. 

It's also true that in a lot of usage schenarios, what people actually 
_use_ is "pull" and "push", and no, they aren't mirror images (since push 
will _not_ do the merge), but at the same time, from a _usage_ standpoint 
they really _are_ each others opposites. 

You "pull" to get other peoples data into your branch (and once you've 
internalized local branches and the merge thing, you know what this 
means), and you "push" to push your changes out. It really _is_ the usage 
schenario, and using "opposite" words really _does_ make sense.

It's true that _technically_ "fetch" is the opposite of "push", but at the 
same time, that really is about technology, not about usage models. You 
normally wouldn't do a "git fetch + git push" pair. You _can_ do so, but 
it's not the natural way to work - unless you're just doing a mirror 
service.

		Linus
-

From: Nicolas Pitre
Date: Wednesday, November 15, 2006 - 2:18 pm

Yeah.  You could always throw a branch to your dog.

Or maybe we should introduce the concept of "bones" to GIT in place of 

Has SCCS really had a similar level of influence than BK or CVS in that 

The problem is the "usage standpoint" distinction that has to be made.  
Exactly because in GIT it is a bit distorted from what most people 

But that's exactly why newbies have problems.  Instead of simply 
understanding the bare operation (fetch data in a branch _then_ merge 
it) they sort of need to abstract the concept of branch away because a 
"pull" does it all automagically.  Which is fine as long as you're 
willing to ignore branch concepts altogether.  But once branches are 
back in the picture for more involved operations then the "pull" word 
simply feels odd.  Even more so with the local merge syntax.

When I say to someone "just merge branch weezee with your current 
branch" the most intuitive command would be:

	git merge weezee

But because "pull" mixes two concepts together this makes the thing more 
esoteric.  Unless, of course, you get used to the mental model you 
outlined above, but IMHO simply needing a mental model to explain the 
tool is a sign that something is mapped wrong.


Nicolas
-

Previous thread: Re: Cleaning up git user-interface warts by Jakub Narebski on Tuesday, November 14, 2006 - 2:01 pm. (4 messages)

Next thread: git-svn and rebase causes duplicate log entries in svn by Joakim Tjernlund on Tuesday, November 14, 2006 - 2:49 pm. (3 messages)