threads / rfc / 21298

[RFC] pull/fetch rename

Subject: [RFC] pull/fetch rename

## tl;dr

32 messages between Oct 20, 2009 and Oct 24, 2009.

replies: 31people: 9as markdown or json

Thomas Rast· Oct 20, 2009, 17:47 UTC · lore
Hi all,

While everyone is busy in two other UI threads, I figured I might as well toss up another (probably) controversial topic.

Especially on IRC, we see many people who are some combination of misunderstanding, misusing or overusing git-pull. I figure this is the result of several factors, notably

a) pull/push are not symmetric,
b) guides/tutorials recommend pull for situations where they
   shouldn't,
c) people blindly fire commands at git.

While the latter two are probably hopeless, I find (a) rather annoying. It breaks everyone's intuition of git-pull when they first see it. (I know that BK has a pull that also merges, but I gather from the manual [never used it] that you cannot do the equivalent of git-fetch in BK.)

As you probably guessed by now, here is an idea for a very aggressive transition plan to address (a) in four phases:

1. git-fetch gets options --merge/-m and --rebase that make it behave
   like (current) git-pull, but requiring explicit arguments.
   git-pull gets a new option --merge (-m) that only enforces presence
   of arguments.
2. git-pull refuses to do any work unless given either --merge or
   --rebase.  Deprecation warnings for this start at the same time as
   (1.).
3. git-pull becomes a synonym for git-fetch.
4. git-fetch gives deprecation warnings that point the user to
   git-pull instead.

(1.) is probably harmless and could be put into any particular release. (2.) obviously breaks everyone's favourite script and needs to fall on a major release. (3.) should be delayed significantly from (2.) to allow time to expose such breakage, and similarly (4.) should be delayed after (3.) (or just ignored, but in any case git-pull would become the preferred spelling).

As you probably noticed, while 'git pull $remote $ref' only needs to be changed to 'git pull --merge $remote $ref', this leaves a gap at the current functionality of 'git pull' without arguments. Björn laid out a nice suggestion for a git-update in

  http://article.gmane.org/gmane.comp.version-control.git/130679

briefly summarised as: git-update would cover what 'git pull' (without arguments) does right now. However, it could also be restricted to fast-forward updates by default (with per-branch configurability as with current git-pull).

Comments?  Flames?  Improvements?
-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Wesley J. Landaker· Oct 20, 2009, 19:59 UTC · re: Thomas Rast · lore

Re: [RFC] pull/fetch rename

On Tuesday 20 October 2009 11:47:45 Thomas Rast wrote:
Show 10 quoted lines
> Especially on IRC, we see many people who are some combination of
> misunderstanding, misusing or overusing git-pull.  I figure this is
> the result of several factors, notably
> 
> a) pull/push are not symmetric,
> 
> b) guides/tutorials recommend pull for situations where they
>    shouldn't,
> 
> c) people blindly fire commands at git.
This may be minor, but also:
d) in mercurial, pull/push are symmetric, but fetch means pull+merge
> As you probably guessed by now, here is an idea for a very aggressive
> transition plan to address (a) in four phases:
I would love to see this change, not because I get confused about pull/fetch 
(it honestly only took a few days to get used to), but because having 
push/pull be symmetric just is so much more conceptually pure / easier 
explain to co-workers / separation between orthogonal operations / 
satisfying to my inner perfectionist / etc.
  
Show 13 quoted lines
> 1. git-fetch gets options --merge/-m and --rebase that make it behave
>    like (current) git-pull, but requiring explicit arguments.
>    git-pull gets a new option --merge (-m) that only enforces presence
>    of arguments.
> 
> 2. git-pull refuses to do any work unless given either --merge or
>    --rebase.  Deprecation warnings for this start at the same time as
>    (1.).
>
> 3. git-pull becomes a synonym for git-fetch.
> 
> 4. git-fetch gives deprecation warnings that point the user to
>    git-pull instead.

Hmmm, maybe this would be better for easier transition; replace 2-4 above with:

2. git-pull learns --merge and gets a configuration option that allows 
turning auto-merging off (e.g. pull.merge = merge/yes (default), rebase, or 
no). This doesn't change any behavior by default, but allows individual 
users to essentially make pull == fetch, and is forward compatible with 
changes up to #4.
3. git-pull gives a deprecation warning if the configuration option is not 
set, but otherwise defaults to merge. To get rid of the warning, you can set 
it explicitly (one way or another).
4. The configuration option default changes to "no", and a helpful message 
is printed telling you that you can set the configuration option to merge to 
get the old behavior.
5. Drop deprecation messages. At this point, git fetch and git pull are 
identical, except git fetch never merges, regardless of the pull 
configuration setting.
This has a few nice properties:
  * There is lots and lots of warning; this transition could happen slowly.
  * Early on, it will be possible to make git pull have symmetric behavior 
by default, which is the desired endgame.
  * In the end, people who want "git pull" to always keep it's current 
behavior can do so by setting the proper configuration variable.
  * git fetch doesn't need to be deprecated (but could be).
Junio C Hamano· Oct 20, 2009, 21:46 UTC · re: Wesley J. Landaker · lore

Re: [RFC] pull/fetch rename

"Wesley J. Landaker" <wjl@icecavern.net> writes:
Show 24 quoted lines
> On Tuesday 20 October 2009 11:47:45 Thomas Rast wrote:
>> Especially on IRC, we see many people who are some combination of
>> misunderstanding, misusing or overusing git-pull.  I figure this is
>> the result of several factors, notably
>> 
>> a) pull/push are not symmetric,
>> 
>> b) guides/tutorials recommend pull for situations where they
>>    shouldn't,
>> 
>> c) people blindly fire commands at git.
>
> This may be minor, but also:
>
> d) in mercurial, pull/push are symmetric, but fetch means pull+merge
>
>> As you probably guessed by now, here is an idea for a very aggressive
>> transition plan to address (a) in four phases:
>
> I would love to see this change, not because I get confused about pull/fetch 
> (it honestly only took a few days to get used to), but because having 
> push/pull be symmetric just is so much more conceptually pure / easier 
> explain to co-workers / separation between orthogonal operations / 
> satisfying to my inner perfectionist / etc.
Is making "pull" a symmetric opposite of "push" the ultimate goal?
Or is making (or rather "keeping") "pull" useful more important?
It is not even an attitude that values philosophy over utility.

Fundamentally, pull and push cannot be symmetric because nobody is sitting in front of the repository you are pushing into (that is what a "push" is; you push from outside the repository---otherwise you would be "pull"ing from inside it in the other direction), but you know you are sitting in the repository, ready to resolve potential conflicts, when you say "pull".

Your elaborate scheme to make "pull" into "fetch" and to force everybody to set a configuration variable to make it "pull" again sounds like a mindless mental masturbation to me. People who leave "pull.merge = no" will always have to say "pull --merge" or "pull --rebase", so you cannot even argue you are not forcing but giving them a choice.

And you are doing this for what gain? The only thing I can think of is "People who deliberately set 'pull.merge = yes' can no longer blame us for pull not being the opposite of push." I do not consider it as a gain.

I do not buy "People who set 'pull.merge = yes' now understand why pull touches their work tree, because they did it themselves" either. People blindly copy other people's configuration from random web pages without understanding. Besides, the next thing they will ask is "Why is there pull.merge but no push.merge? Wasn't push an opposite of pull?" and you are back to square one.

I would be much more sympathetic if the suggested approach were to make "push" more symmetric to "pull", or at least attempt to allow it to be, by giving it an option to update the associated work tree when it can [*1*].

But I do not know what to say when people say "push cannot update the work tree, so let's make pull not to update the work tree by default---it will make it much less useful so we will fix that regression with yet another configuration option". It's not even funny.

[Footnote]

*1* Obviously you cannot do this most of the time _if_ the work tree has an interactive user sitting in front of it, but in a repository that never allows a non-ff push, with a work tree that is never updated except by such a push, can reasonably be maintained to give an illusion of push being an opposite of pull by fast forwarding the work tree when the push updates HEAD.

Thomas Rast· Oct 20, 2009, 22:53 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

Junio C Hamano wrote:
> "Wesley J. Landaker" <wjl@icecavern.net> writes:
> > d) in mercurial, pull/push are symmetric, but fetch means pull+merge

Ugh. I can see how they arrived at hg-pull == git-fetch, but why on earth was the logical next step hg-fetch == git-pull?!

</aside>
Show 17 quoted lines
> > I would love to see this change, not because I get confused about pull/fetch 
> > (it honestly only took a few days to get used to), but because having 
> > push/pull be symmetric just is so much more conceptually pure / easier 
> > explain to co-workers / separation between orthogonal operations / 
> > satisfying to my inner perfectionist / etc.
> 
> Is making "pull" a symmetric opposite of "push" the ultimate goal?
> 
> Or is making (or rather "keeping") "pull" useful more important?
> 
> It is not even an attitude that values philosophy over utility.
> 
> Fundamentally, pull and push cannot be symmetric because nobody is sitting
> in front of the repository you are pushing into (that is what a "push" is;
> you push from outside the repository---otherwise you would be "pull"ing
> from inside it in the other direction), but you know you are sitting in
> the repository, ready to resolve potential conflicts, when you say "pull".

Well, I'd rather not argue the little semantic details, but I think with the changes to disallow pushing into HEAD, push and fetch are as symmetric as it gets. Both are exactly and only about transmitting refs with their associated commits to the other side. Which one you pick only depends on which side you sit on.

OTOH pull is about merging. And we can repeat the "pull = fetch + merge" mantra to ourselves all we like, having pull as "the opposite of push" is conceptually much easier to understand and thus far easier to explain to new users.

Show 6 quoted lines
> And you are doing this for what gain?  The only thing I can think of is
> "People who deliberately set 'pull.merge = yes' can no longer blame us for
> pull not being the opposite of push."  I do not consider it as a gain.
> 
> I do not buy "People who set 'pull.merge = yes' now understand why pull
> touches their work tree, because they did it themselves" either.
[...]
> But I do not know what to say when people say "push cannot update the work
> tree, so let's make pull not to update the work tree by default---it will
> make it much less useful so we will fix that regression with yet another
> configuration option".
There would not be a configuration option.

Really, the whole goal would be to make pull the opposite of push. No exceptions, and most certainly no little loopholes to escape into the merging behaviour by default. The current 'git pull' behaviour would either be obtained through a new command, or through an explicit switch.

> I would be much more sympathetic if the suggested approach were to make
> "push" more symmetric to "pull", or at least attempt to allow it to be, by
> giving it an option to update the associated work tree when it can [*1*].
[...]
Show 6 quoted lines
> *1* Obviously you cannot do this most of the time _if_ the work tree has
> an interactive user sitting in front of it, but in a repository that never
> allows a non-ff push, with a work tree that is never updated except by
> such a push, can reasonably be maintained to give an illusion of push
> being an opposite of pull by fast forwarding the work tree when the push
> updates HEAD.
Well, that reminds me of
  http://thread.gmane.org/gmane.comp.version-control.git/110251
but was not really what I was aiming at.
> It's not even funny.
It was an RFC, not a joke ;-)
-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Junio C Hamano· Oct 20, 2009, 23:11 UTC · re: Thomas Rast · lore

Re: [RFC] pull/fetch rename

Thomas Rast <trast@student.ethz.ch> writes:
Show 6 quoted lines
> Junio C Hamano wrote:
>> "Wesley J. Landaker" <wjl@icecavern.net> writes:
> ...
> There would not be a configuration option.
> ...
>> It's not even funny.

Re-read what you were responding to and notice that I was commenting on Wesley's proposal that _is_ about a configuration variable.

Wesley J. Landaker· Oct 21, 2009, 02:01 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

On Tuesday 20 October 2009 17:11:32 Junio C Hamano wrote:
Show 12 quoted lines
> Thomas Rast <trast@student.ethz.ch> writes:
> > Junio C Hamano wrote:
> >> "Wesley J. Landaker" <wjl@icecavern.net> writes:
> >
> > ...
> > There would not be a configuration option.
> > ...
> >
> >> It's not even funny.
> 
> Re-read what you were responding to and notice that I was commenting on
> Wesley's proposal that _is_ about a configuration variable.
Yes, I brought up the configuration variable, not Thomas. 

My main goal was to try to suggest a transition plan that would be less painful, but maybe it was actually worse. After reading Junio's response I think I agree that going down that path might be the worst of both worlds, but the basic model I was proposing (even if it's a bad idea in this case) was largely basing on (my perceived impression of) how the recent changes to push behavior were staged (i.e. with deprecation, new configuration variables, etc).

I still think that, long term, making push and pull symmetric, EITHER by 1) making push also update the working tree (in some sane way that I don't have a proposal for) or 2) making pull be just about transfering objects, not also merging (in some reasonable way that doesn't break useability, like also adding "git update" or something at the same time) would be an overall benefit.

Junio C Hamano· Oct 20, 2009, 23:16 UTC · re: Thomas Rast · lore

Re: [RFC] pull/fetch rename

Thomas Rast <trast@student.ethz.ch> writes:
Show 5 quoted lines
> Well, that reminds me of
>
>   http://thread.gmane.org/gmane.comp.version-control.git/110251
>
> but was not really what I was aiming at.

Actually, if that patch weren't marked as [DRY HUMOR PATCH], and if it did not have the detachInstead option, I would have at least queued it to 'pu', if not 'next'.

Nanako Shiraishi· Oct 20, 2009, 21:42 UTC · re: Thomas Rast · lore

Re: [RFC] pull/fetch rename

Quoting Thomas Rast <trast@student.ethz.ch>
Show 40 quoted lines
> Especially on IRC, we see many people who are some combination of
> misunderstanding, misusing or overusing git-pull.  I figure this is
> the result of several factors, notably
>
> a) pull/push are not symmetric,
>
> b) guides/tutorials recommend pull for situations where they
>    shouldn't,
>
> c) people blindly fire commands at git.
>
> While the latter two are probably hopeless, I find (a) rather
> annoying.  It breaks everyone's intuition of git-pull when they first
> see it.  (I know that BK has a pull that also merges, but I gather
> from the manual [never used it] that you cannot do the equivalent of
> git-fetch in BK.)
>
> As you probably guessed by now, here is an idea for a very aggressive
> transition plan to address (a) in four phases:
>
> 1. git-fetch gets options --merge/-m and --rebase that make it behave
>    like (current) git-pull, but requiring explicit arguments.
>    git-pull gets a new option --merge (-m) that only enforces presence
>    of arguments.
>
> 2. git-pull refuses to do any work unless given either --merge or
>    --rebase.  Deprecation warnings for this start at the same time as
>    (1.).
>
> 3. git-pull becomes a synonym for git-fetch.
>
> 4. git-fetch gives deprecation warnings that point the user to
>    git-pull instead.
>
> (1.) is probably harmless and could be put into any particular
> release.  (2.) obviously breaks everyone's favourite script and needs
> to fall on a major release.  (3.) should be delayed significantly from
> (2.) to allow time to expose such breakage, and similarly (4.) should
> be delayed after (3.) (or just ignored, but in any case git-pull would
> become the preferred spelling).

Sorry, but I don't understand what's the improvement in the end result.

I started reading your problem description and I thought you are fixing your item 'a) pull/push are not symmetric' by deprecating pull, to advertize fetch/push. Then asymmetry of push/pull stops being an issue.

But it seems that eventually you will keep git-push and git-pull (because git-fetch gets deprecated); you have push/pull that are not symmetric.

What's the point of this change then?
-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
Thomas Rast· Oct 20, 2009, 22:41 UTC · re: Nanako Shiraishi · lore

Re: [RFC] pull/fetch rename

Nanako Shiraishi wrote:
Show 26 quoted lines
> Quoting Thomas Rast <trast@student.ethz.ch>
> > 1. git-fetch gets options --merge/-m and --rebase that make it behave
> >    like (current) git-pull, but requiring explicit arguments.
> >    git-pull gets a new option --merge (-m) that only enforces presence
> >    of arguments.
> >
> > 2. git-pull refuses to do any work unless given either --merge or
> >    --rebase.  Deprecation warnings for this start at the same time as
> >    (1.).
> >
> > 3. git-pull becomes a synonym for git-fetch.
> >
> > 4. git-fetch gives deprecation warnings that point the user to
> >    git-pull instead.
> 
> Sorry, but I don't understand what's the improvement in the end 
> result.
> 
> I started reading your problem description and I thought you are 
> fixing your item 'a) pull/push are not symmetric' by deprecating 
> pull, to advertize fetch/push.  Then asymmetry of push/pull stops 
> being an issue.
> 
> But it seems that eventually you will keep git-push and git-pull 
> (because git-fetch gets deprecated); you have push/pull that are 
> not symmetric.

By the time I get to that step, new-pull is current-fetch. So by that time, push/pull *are* supposedly symmetric.

(Only deprecating pull never occurred to me, but then I really think the strong association between them makes it worth keeping pull as the opposite of push.)

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Daniel Barkalow· Oct 20, 2009, 23:56 UTC · re: Thomas Rast · lore

Re: [RFC] pull/fetch rename

On Tue, 20 Oct 2009, Thomas Rast wrote:
Show 10 quoted lines
> Hi all,
> 
> While everyone is busy in two other UI threads, I figured I might as
> well toss up another (probably) controversial topic.
> 
> Especially on IRC, we see many people who are some combination of
> misunderstanding, misusing or overusing git-pull.  I figure this is
> the result of several factors, notably
> 
> a) pull/push are not symmetric,

In a certain sense they are; they both update the branches local to one repository with the data from the other repository. In this sense, fetch is the oddity in that it doesn't update any repository's own branches, but just the local information about other repositories' branches.

In another sense, push is unlike anything else in that it updates something that's remote; in a third sense, pull is unique in that it can generate a merge.

I suspect that what we've called "fetch" isn't what the people want when they type "pull", either. And I suspect that the fundamental issue is that the operation people are looking for is not the operation that they would do best to use, regardless of naming. I think users are looking for something that corresponds to "svn up", and they find "git pull"; this isn't going to make them happy git users, but finding "git fetch" instead is going to make them even more confused.

But I don't really know; are there IRC logs you can quote or reference with people making the mistake you're trying to help them avoid?

	-Daniel
*This .sig left intentionally blank*
Björn Steinbrink· Oct 21, 2009, 03:06 UTC · re: Daniel Barkalow · lore

Re: [RFC] pull/fetch rename

On 2009.10.20 19:56:01 -0400, Daniel Barkalow wrote:
> But I don't really know; are there IRC logs you can quote or reference 
> with people making the mistake you're trying to help them avoid?

"git pull" is kind of a jack of all trades WRT user errors, so I'll just pick up examples of all kinds, this might get long...

[If you read this and find out that you're quoted/referenced here: I don't mean to blame or embarrass you, or to point out that you're stupid or whatever. Quite contrary, I just want to show how git's pull UI _might_ be responsible for your mistakes. The comments I made are purely my, possibly biased, reaction to what happened.]

That said, here we go:
1) Unexpected fast-forward even with --no-ff
"git pull --no-ff abc:abc" with "abc" being checked out.

As pull explicitly allows fetches into the checked out branch head, this first fast-forwards abc, and updates the working tree/index. And then the --no-ff merge is a no-op.

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l2080 (Should be a catchable special case, and the special --update-head-ok handling of "git pull" is from times where git didn't have remote tracking branches. I'd argue that that support should be dropped or at least disabled when you're using the modern setup, might be kept for oldtimers still using .git/remotes/*. Dunno...)

2) "git pull" taken as "reset --hard"
git checkout -b foo; git pull origin bar

The user actually just wanted to look at things and thus was ok with: git fetch origin; git checkout origin/bar

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l1807 (user seemed to be so inclined to use "pull" that he initially didn't even realize that he didn't want to merge when I asked whether that's what he wants)

3) User expects "pull" to update all branch heads that have a configured
upstream
08:31 	dimsuz 	hi guys! suppose i'm currently on master. then run git
		fetch. which delivers updates to master and other
		branches. I don't merge anything, but do checkout some
		branch (which is not master).  Question: will these new
		updates get into this branch automatically after i check
		it out? question2: will branch master contain those
		updates when i ckeck it out later?
08:32 	Circuitsoft 	dimsuz. After a fetch, no.
08:33 	Circuitsoft 	However, if you pull, any branches that were set
			up as local tracking branches will get updated.
08:33 	Circuitsoft 	Otherwise, only remote tracking branches will be
			updated.

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l969 (No idea about that one, have seen that once before, but it's definitely not even remotely as common as the others)

4) User expects "pull" to create branches
07:25 	fynn 	Hey, I just pulled a branch from remote, and I don't see
		it in "git branch"
07:25 	doener 	fynn: if you "pull" that means "fetch this and merge it
		to what I have checked out"
07:25 	fynn 	doener: hm, I just did "git pull" and it showed the new
		branch
07:26 	fynn 	but I don't see it in my branches...
07:26 	fynn 	doener: should I create that branch as a tracking branch
		first?
07:26 	doener 	fynn: you're looking at "git branch -r" or "git branch
		-a", right?
07:26 	fynn 	doener: yeah, I'm seeing it in origin/foo, but not
		local.
07:26 	doener 	fynn: the "git fetch" should have created a remote
		tracking branch, as usual, not a local branch head
		(which would be shown by just "git branch")
07:27 	fynn 	doener: OK, what should I do to create it locally then?
07:28 	doener 	fynn: just the usual "git branch foo origin/foo", or to
		checkout at the same time: "git checkout -b foo
		origin/foo" or "git checkout -t origin/foo" (shortcut)

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-19#l830 (Note how my "fetch this and merge it" is actually inaccurate for just "git pull", there is no "this" and that case. I took "pulled a branch" to mean that he did "git pull <remote> <branch>", which wouldn't have created/update the remote tracking branch [or did patches for that go in? I lost track...])

4b) User expects pull to create a branch head

09:58 araujo git pull origin <new_branch> 09:58 araujo will get me the new branch from repo right? 10:00 charon araujo: no, that will fetch *and merge* that branch 10:00 araujo charon, how to just pull?

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-19#l1152 (Note how he asked "how to just pull?", even after being told that pull isn't what he wants)

5) User possibly expecting "pull" to be able to act as "reset --hard"
21:01 	aidan 	What do I do about this: html/config/core.php: needs
		update
21:02 	aidan 	git pull (gives that)
21:02 	Ilari 	aidan: You have uncommitted changes to that file...
21:15 	aidan 	Ilari: how can I just pull master and overwrite any
		changes?

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-18#l2130 (I'm not sure about that one, "overwrite any changes" might mean "drop uncommitted changes and merge" or "just get me the remote's state, dropping my commits and uncommitted changes". Most of the time I've seen similar requests, the user wanted the latter).

6) User says "pull" but probably means "fetch"
14:08 	Alien_Freak 	once I have a clone of a repo I know you can do
			a checkout tag but is there anyway to pull just
			the tag?

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-16#l1664 (There was no answer, thus it's hard to tell, but I guess he wanted something like: git init; git fetch --no-tags url tag <tag>; git checkout <tag> At least I'm quite sure he didn't mean "pull" as in "git pull")

7) User expecting "pull" to just do fast-forwards (or so)
13:18 	ohadlevy 	I'm getting a merge commit message after each
			time i do git pull, i didnt have it before,
			where should I look?
13:20 	charon 	ohadlevy: pull merges; you may just have hit lucky so
		far, and always had a fast-forward merge
13:20 	ohadlevy 	charon: any way I could avoid these commits?
			just rebasing? its a pure RO repo

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-16#l1579 (Apparently, user was tricked by the fast-forward behaviour he experienced earlier. I don't see any solution to this, except for defaulting to fast-forward-only and requiring a --merge flag (which might imply --no-ff), but I'm likely influenced by the "git update" stuff here)

8) "reset --hard" again
20:10 	roger_padactor 	i commited then did a pull how do i get back to
			my commit. the pull over wrote the files
20:11 	merlin83 	roger_padactor: you can't, pull == fetch + hard
			reset to latest commit

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-14#l2306 (Someone being told that pull is fetch + reset --hard is actually new to me. Only saw that as an expectation previously.)

9) More "git pull <remote> A:A"
19:10 	_hp_ 	another question, how do I add the remote branch to
		track so I don't have to constantly do git pull origin
		masterA:masterA ?
19:11 	Ilari 	_hp_: Don't use that src:dest with pull!
(discussion died)
http://colabti.de/irclogger/irclogger_log/git?date=2009-10-12#l2427
10) "pull" mistaken for "cvs update"
07:25 	Avrem 	how do I use "git pull" to do something like what "cvs
		update" does ?
07:25 	Avrem 	which is, replaces files I've deleted
07:25 	Avrem 	from that from the central repository
07:30 	omega 	I'm not sure, but can't you git checkout <deleted files>
		to get them back?

http://colabti.de/irclogger/irclogger_log/git?date=2009-10-11#l545 (This adds a new twist to the "scm update" stuff, although svn/hg don't seem to have "restore individual files" in their "update" command, so this might be cvs-only. But it's so long since I used cvs, I don't even know whether this is correct. But it somehow got me thinking about how "update" is actually also "downgrade" in svn/hg, something git does via "checkout" [which happens to make more sense to me]. And I think it shows how "git pull" is taken to mean "update", even when ignoring the special behaviour described here. It's not taken to mean "merge this", but just "update to upstream").

So that's ten days of #git. I left out a bunch of duplications (most were "pull == fetch", "pull == update" and "pull to update non-checked-out branch").

Björn
Daniel Barkalow· Oct 21, 2009, 04:22 UTC · re: Björn Steinbrink · lore

Re: [RFC] pull/fetch rename

On Wed, 21 Oct 2009, Björn Steinbrink wrote:
Show 29 quoted lines
> On 2009.10.20 19:56:01 -0400, Daniel Barkalow wrote:
> > But I don't really know; are there IRC logs you can quote or reference 
> > with people making the mistake you're trying to help them avoid?
> 
> "git pull" is kind of a jack of all trades WRT user errors, so I'll just
> pick up examples of all kinds, this might get long...
> 
> [If you read this and find out that you're quoted/referenced here: I
> don't mean to blame or embarrass you, or to point out that you're stupid
> or whatever. Quite contrary, I just want to show how git's pull UI _might_
> be responsible for your mistakes. The comments I made are purely my,
> possibly biased, reaction to what happened.]
> 
> That said, here we go:
> 
> 1) Unexpected fast-forward even with --no-ff
> 
> "git pull --no-ff abc:abc" with "abc" being checked out.
> 
> As pull explicitly allows fetches into the checked out branch head, this
> first fast-forwards abc, and updates the working tree/index. And then
> the --no-ff merge is a no-op.
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l2080
> (Should be a catchable special case, and the special --update-head-ok
> handling of "git pull" is from times where git didn't have remote
> tracking branches. I'd argue that that support should be dropped or at
> least disabled when you're using the modern setup, might be kept for
> oldtimers still using .git/remotes/*. Dunno...)

Yup, I think it would be good to ditch --update-head-ok and simplify the code; I also think it would be nice to prohibit fetching into refs/heads/* entirely, but there might be advanced users who actually want to do that.

In this case, "git fetch" has already done something the user didn't want, and the pull-specific portion doesn't actually do anything at all.

Show 10 quoted lines
> 2) "git pull" taken as "reset --hard"
> git checkout -b foo; git pull origin bar
> 
> The user actually just wanted to look at things and thus was ok with:
> git fetch origin; git checkout origin/bar
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l1807
> (user seemed to be so inclined to use "pull" that he initially didn't
> even realize that he didn't want to merge when I asked whether that's
> what he wants)

I think that's a case where the user has been discouraged from using detached HEAD, and is using "pull" instead of "fetch" in order to update the junk branch he doesn't actually want. If you don't know you don't need a local branch, and you branch off of a common ancestor, "pull" does actually do something you want that "fetch" doesn't.

Show 19 quoted lines
> 3) User expects "pull" to update all branch heads that have a configured
> upstream
> 
> 08:31 	dimsuz 	hi guys! suppose i'm currently on master. then run git
> 		fetch. which delivers updates to master and other
> 		branches. I don't merge anything, but do checkout some
> 		branch (which is not master).  Question: will these new
> 		updates get into this branch automatically after i check
> 		it out? question2: will branch master contain those
> 		updates when i ckeck it out later?
> 08:32 	Circuitsoft 	dimsuz. After a fetch, no.
> 08:33 	Circuitsoft 	However, if you pull, any branches that were set
> 			up as local tracking branches will get updated.
> 08:33 	Circuitsoft 	Otherwise, only remote tracking branches will be
> 			updated.
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l969
> (No idea about that one, have seen that once before, but it's definitely
> not even remotely as common as the others)

I'd guess that's due to having local branches with no local changes, just to avoid detached HEAD, and therefore thinking it's normal to have a bunch of local branches that could be updated without merges. But I'm on a crazy "everybody really wants detached HEAD and is needlessly scared" kick, and I'm probably reading too much into it.

Show 29 quoted lines
> 4) User expects "pull" to create branches
> 
> 07:25 	fynn 	Hey, I just pulled a branch from remote, and I don't see
> 		it in "git branch"
> 07:25 	doener 	fynn: if you "pull" that means "fetch this and merge it
> 		to what I have checked out"
> 07:25 	fynn 	doener: hm, I just did "git pull" and it showed the new
> 		branch
> 07:26 	fynn 	but I don't see it in my branches...
> 07:26 	fynn 	doener: should I create that branch as a tracking branch
> 		first?
> 07:26 	doener 	fynn: you're looking at "git branch -r" or "git branch
> 		-a", right?
> 07:26 	fynn 	doener: yeah, I'm seeing it in origin/foo, but not
> 		local.
> 07:26 	doener 	fynn: the "git fetch" should have created a remote
> 		tracking branch, as usual, not a local branch head
> 		(which would be shown by just "git branch")
> 07:27 	fynn 	doener: OK, what should I do to create it locally then?
> 07:28 	doener 	fynn: just the usual "git branch foo origin/foo", or to
> 		checkout at the same time: "git checkout -b foo
> 		origin/foo" or "git checkout -t origin/foo" (shortcut)
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-19#l830
> (Note how my "fetch this and merge it" is actually inaccurate for just
> "git pull", there is no "this" and that case. I took "pulled a branch"
> to mean that he did "git pull <remote> <branch>", which wouldn't have
> created/update the remote tracking branch [or did patches for that go
> in? I lost track...])

That sounds like a real converse of "push", including creating like-named local branches. Or, perhaps, this is someone expecting that "pull" is like "clone" in creating an initial local branch with the name and value of a specified remote branch.

Show 10 quoted lines
> 4b) User expects pull to create a branch head
> 
> 09:58 	araujo 	git pull origin <new_branch>
> 09:58 	araujo 	will get me the new branch from repo right?
> 10:00 	charon 	araujo: no, that will fetch *and merge* that branch
> 10:00 	araujo 	charon, how to just pull?
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-19#l1152
> (Note how he asked "how to just pull?", even after being told that pull
> isn't what he wants)

That's got to be hg usage. He knows the command isn't "pull", but he's stuck with the operation it performs being pulling. Or maybe he's thinking that the operation is pulling, and the command needs different arguments to not merge.

Show 14 quoted lines
> 5) User possibly expecting "pull" to be able to act as "reset --hard"
> 
> 21:01 	aidan 	What do I do about this: html/config/core.php: needs
> 		update
> 21:02 	aidan 	git pull (gives that)
> 21:02 	Ilari 	aidan: You have uncommitted changes to that file...
> 21:15 	aidan 	Ilari: how can I just pull master and overwrite any
> 		changes?
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-18#l2130
> (I'm not sure about that one, "overwrite any changes" might mean "drop
> uncommitted changes and merge" or "just get me the remote's state,
> dropping my commits and uncommitted changes". Most of the time I've seen
> similar requests, the user wanted the latter).

So I think that's a desire for "git checkout ." first of all (with the assumption that the content without modifications has to come from somewhere remote). I don't know what's up with people not wanting to save their commits, though.

Show 11 quoted lines
> 6) User says "pull" but probably means "fetch"
> 
> 14:08 	Alien_Freak 	once I have a clone of a repo I know you can do
> 			a checkout tag but is there anyway to pull just
> 			the tag?
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-16#l1664
> (There was no answer, thus it's hard to tell, but I guess he wanted
> something like:
> git init; git fetch --no-tags url tag <tag>; git checkout <tag>
> At least I'm quite sure he didn't mean "pull" as in "git pull")
I don't know; you can actually do:
$ git init; git pull --no-tags <url> tag <tag>

It updates the master branch and working directory from (nothing) to the fetched tag.

Show 16 quoted lines
> 7) User expecting "pull" to just do fast-forwards (or so)
> 
> 13:18 	ohadlevy 	I'm getting a merge commit message after each
> 			time i do git pull, i didnt have it before,
> 			where should I look?
> 13:20 	charon 	ohadlevy: pull merges; you may just have hit lucky so
> 		far, and always had a fast-forward merge
> 13:20 	ohadlevy 	charon: any way I could avoid these commits?
> 			just rebasing? its a pure RO repo
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-16#l1579
> (Apparently, user was tricked by the fast-forward behaviour he
> experienced earlier. I don't see any solution to this, except for
> defaulting to fast-forward-only and requiring a --merge flag (which
> might imply --no-ff), but I'm likely influenced by the "git update"
> stuff here)

Again, sounds like the user does want to update local branch state, if there is any. Probably doesn't want a local branch, what with being confused at the possibility of having history that's not from the remote.

Show 10 quoted lines
> 8) "reset --hard" again
> 
> 20:10 	roger_padactor 	i commited then did a pull how do i get back to
> 			my commit. the pull over wrote the files
> 20:11 	merlin83 	roger_padactor: you can't, pull == fetch + hard
> 			reset to latest commit
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-14#l2306
> (Someone being told that pull is fetch + reset --hard is actually new to
> me. Only saw that as an expectation previously.)

That's odd. How could you not notice that it doesn't actually do that, even if you try to get it to?

Show 9 quoted lines
> 9) More "git pull <remote> A:A"
> 
> 19:10 	_hp_ 	another question, how do I add the remote branch to
> 		track so I don't have to constantly do git pull origin
> 		masterA:masterA ?
> 19:11 	Ilari 	_hp_: Don't use that src:dest with pull!
> (discussion died)
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-12#l2427

Yup. Oh, and it strikes me that this user must have never made any commits, because that would give an error (not fast forward) on the fetch part.

Show 19 quoted lines
> 10) "pull" mistaken for "cvs update"
> 
> 07:25 	Avrem 	how do I use "git pull" to do something like what "cvs
> 		update" does ?
> 07:25 	Avrem 	which is, replaces files I've deleted
> 07:25 	Avrem 	from that from the central repository
> 07:30 	omega 	I'm not sure, but can't you git checkout <deleted files>
> 		to get them back?
> 
> http://colabti.de/irclogger/irclogger_log/git?date=2009-10-11#l545
> (This adds a new twist to the "scm update" stuff, although svn/hg don't
> seem to have "restore individual files" in their "update" command, so
> this might be cvs-only. But it's so long since I used cvs, I don't even
> know whether this is correct. But it somehow got me thinking about how
> "update" is actually also "downgrade" in svn/hg, something git does via
> "checkout" [which happens to make more sense to me]. And I think it
> shows how "git pull" is taken to mean "update", even when ignoring the
> special behaviour described here. It's not taken to mean "merge this",
> but just "update to upstream").

"cvs update" can definitely discard uncommitted changes, according to the --help text.

Actually, I wonder if the right formula is update = fetch + checkout. There are a lot of people (IMHO) want "git fetch origin; git checkout origin/master", and I think their first idea is "git update", but that doesn't exist, and they find "pull" as the closest thing.

> So that's ten days of #git. I left out a bunch of duplications (most
> were "pull == fetch", "pull == update" and "pull to update
> non-checked-out branch").

Very interesting. I feel like this is a new thing since I last spent much time on IRC, when it was all people pushing into non-bare repositories. Thanks for taking the time to collect this.

	-Daniel
*This .sig left intentionally blank*
Björn Steinbrink· Oct 21, 2009, 11:57 UTC · re: Daniel Barkalow · lore

Re: [RFC] pull/fetch rename

On 2009.10.21 00:22:18 -0400, Daniel Barkalow wrote:
Show 27 quoted lines
> On Wed, 21 Oct 2009, Björn Steinbrink wrote:
> 
> > 3) User expects "pull" to update all branch heads that have a configured
> > upstream
> > 
> > 08:31 	dimsuz 	hi guys! suppose i'm currently on master. then run git
> > 		fetch. which delivers updates to master and other
> > 		branches. I don't merge anything, but do checkout some
> > 		branch (which is not master).  Question: will these new
> > 		updates get into this branch automatically after i check
> > 		it out? question2: will branch master contain those
> > 		updates when i ckeck it out later?
> > 08:32 	Circuitsoft 	dimsuz. After a fetch, no.
> > 08:33 	Circuitsoft 	However, if you pull, any branches that were set
> > 			up as local tracking branches will get updated.
> > 08:33 	Circuitsoft 	Otherwise, only remote tracking branches will be
> > 			updated.
> > 
> > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l969
> > (No idea about that one, have seen that once before, but it's definitely
> > not even remotely as common as the others)
> 
> I'd guess that's due to having local branches with no local changes, just 
> to avoid detached HEAD, and therefore thinking it's normal to have a bunch 
> of local branches that could be updated without merges. But I'm on a crazy 
> "everybody really wants detached HEAD and is needlessly scared" kick, and 
> I'm probably reading too much into it.

Just to clarify: I didn't mean the question (which I didn't really understand) in this case, but the answer from Circuitsoft (second to last line). But maybe you also meant that? The question confuses me enough not to be able to follow.

Show 34 quoted lines
> > 4) User expects "pull" to create branches
> > 
> > 07:25 	fynn 	Hey, I just pulled a branch from remote, and I don't see
> > 		it in "git branch"
> > 07:25 	doener 	fynn: if you "pull" that means "fetch this and merge it
> > 		to what I have checked out"
> > 07:25 	fynn 	doener: hm, I just did "git pull" and it showed the new
> > 		branch
> > 07:26 	fynn 	but I don't see it in my branches...
> > 07:26 	fynn 	doener: should I create that branch as a tracking branch
> > 		first?
> > 07:26 	doener 	fynn: you're looking at "git branch -r" or "git branch
> > 		-a", right?
> > 07:26 	fynn 	doener: yeah, I'm seeing it in origin/foo, but not
> > 		local.
> > 07:26 	doener 	fynn: the "git fetch" should have created a remote
> > 		tracking branch, as usual, not a local branch head
> > 		(which would be shown by just "git branch")
> > 07:27 	fynn 	doener: OK, what should I do to create it locally then?
> > 07:28 	doener 	fynn: just the usual "git branch foo origin/foo", or to
> > 		checkout at the same time: "git checkout -b foo
> > 		origin/foo" or "git checkout -t origin/foo" (shortcut)
> > 
> > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-19#l830
> > (Note how my "fetch this and merge it" is actually inaccurate for just
> > "git pull", there is no "this" and that case. I took "pulled a branch"
> > to mean that he did "git pull <remote> <branch>", which wouldn't have
> > created/update the remote tracking branch [or did patches for that go
> > in? I lost track...])
> 
> That sounds like a real converse of "push", including creating like-named 
> local branches. Or, perhaps, this is someone expecting that "pull" is like 
> "clone" in creating an initial local branch with the name and value of a 
> specified remote branch.

Reading that one again, I realize that I've still been confused by the "pulled a branch". What happened was that the user did "git pull", which ran "git fetch <remote>", which fetched a new branch head and has shown that. At that point, the user (and me) got confused for maybe two reasons:

a) He didn't clearly distinguish between the fetch and the merge part. The new branch wasn't pulled, but just fetched. That caused the user to think that he "pulled the branch" (wrong terminology), which in term confused me (wrong use-case assumed).

b) He expected local branch heads to be created, instead of remote tracking branches. If my memory doesn't play tricks on me, that's actually not to be expected from that specific user (I think we told him about remote tracking branches before, and the last part of the conversation actually suggests that, too). If I don't forget, I'll try to get feedback from him the next time he's around.

Show 19 quoted lines
> > 5) User possibly expecting "pull" to be able to act as "reset --hard"
> > 
> > 21:01 	aidan 	What do I do about this: html/config/core.php: needs
> > 		update
> > 21:02 	aidan 	git pull (gives that)
> > 21:02 	Ilari 	aidan: You have uncommitted changes to that file...
> > 21:15 	aidan 	Ilari: how can I just pull master and overwrite any
> > 		changes?
> > 
> > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-18#l2130
> > (I'm not sure about that one, "overwrite any changes" might mean "drop
> > uncommitted changes and merge" or "just get me the remote's state,
> > dropping my commits and uncommitted changes". Most of the time I've seen
> > similar requests, the user wanted the latter).
> 
> So I think that's a desire for "git checkout ." first of all (with the 
> assumption that the content without modifications has to come from 
> somewhere remote). I don't know what's up with people not wanting to save 
> their commits, though.

You haven't seen the multitude of "I have merge conflicts and just want to take theirs/mine" requests. That often gets more weird than just "drop my commits" ;-)

Show 18 quoted lines
> > 6) User says "pull" but probably means "fetch"
> > 
> > 14:08 	Alien_Freak 	once I have a clone of a repo I know you can do
> > 			a checkout tag but is there anyway to pull just
> > 			the tag?
> > 
> > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-16#l1664
> > (There was no answer, thus it's hard to tell, but I guess he wanted
> > something like:
> > git init; git fetch --no-tags url tag <tag>; git checkout <tag>
> > At least I'm quite sure he didn't mean "pull" as in "git pull")
> 
> I don't know; you can actually do:
> 
> $ git init; git pull --no-tags <url> tag <tag>
> 
> It updates the master branch and working directory from (nothing) to the 
> fetched tag.

Hm, yeah, that works (didn't think of it), but it's a rather special case. Teaching that might lead to misunderstandings about what "pull" does, I think. It would look somewhat like "fetch + reset --hard".

Show 13 quoted lines
> > 8) "reset --hard" again
> > 
> > 20:10 	roger_padactor 	i commited then did a pull how do i get back to
> > 			my commit. the pull over wrote the files
> > 20:11 	merlin83 	roger_padactor: you can't, pull == fetch + hard
> > 			reset to latest commit
> > 
> > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-14#l2306
> > (Someone being told that pull is fetch + reset --hard is actually new to
> > me. Only saw that as an expectation previously.)
> 
> That's odd. How could you not notice that it doesn't actually do that, 
> even if you try to get it to?

Hm? roger_padactor noticed that "pull" changed his files and wants to go back. And merlin83 says that that is impossible because pull supposedly does reset --hard. There's nothing in there (I could see) that suggests that anyone tried to make "pull" do "reset --hard".

merlin83 basically made three mistakes, I think:
1) Assume that roger_padactor was talking about uncommitted changes
2) Assume that pull is fetch + reset --hard
3) Assume that you can't undo a reset --hard for committed changes

(OK, 3) isn't actually valid when you consider 1), but 1) is so invalid that I kept 3). After all, "pull" would complain about a dirty tree...)

> Actually, I wonder if the right formula is update = fetch + checkout. 
> There are a lot of people (IMHO) want "git fetch origin; git checkout 
> origin/master", and I think their first idea is "git update", but that 
> doesn't exist, and they find "pull" as the closest thing.

That has a precondition that the user is already using a detached HEAD. Otherwise that fetch + checkout would likely mean that the get baffled when they do: git checkout master git update git checkout foo git checkout master

Seeing that "master" is out of date "again".

I agree though, that users might look for "git update" and because it is missing, they just look for the closest thing. Adding Junio's statement that users seem to want recipes instead of flexibility (and seeing "update" as just "get me new stuff from upstream" without meaning any specific method of updating), I think that "git update" could be a "recipe collection" tool. I'll hack that into my proof-of-concept thing (which I hope to have ready for a RFC next week).

Björn
Daniel Barkalow· Oct 21, 2009, 17:12 UTC · re: Björn Steinbrink · lore

Re: [RFC] pull/fetch rename

On Wed, 21 Oct 2009, Björn Steinbrink wrote:
Show 33 quoted lines
> On 2009.10.21 00:22:18 -0400, Daniel Barkalow wrote:
> > On Wed, 21 Oct 2009, Björn Steinbrink wrote:
> > 
> > > 3) User expects "pull" to update all branch heads that have a configured
> > > upstream
> > > 
> > > 08:31 	dimsuz 	hi guys! suppose i'm currently on master. then run git
> > > 		fetch. which delivers updates to master and other
> > > 		branches. I don't merge anything, but do checkout some
> > > 		branch (which is not master).  Question: will these new
> > > 		updates get into this branch automatically after i check
> > > 		it out? question2: will branch master contain those
> > > 		updates when i ckeck it out later?
> > > 08:32 	Circuitsoft 	dimsuz. After a fetch, no.
> > > 08:33 	Circuitsoft 	However, if you pull, any branches that were set
> > > 			up as local tracking branches will get updated.
> > > 08:33 	Circuitsoft 	Otherwise, only remote tracking branches will be
> > > 			updated.
> > > 
> > > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-20#l969
> > > (No idea about that one, have seen that once before, but it's definitely
> > > not even remotely as common as the others)
> > 
> > I'd guess that's due to having local branches with no local changes, just 
> > to avoid detached HEAD, and therefore thinking it's normal to have a bunch 
> > of local branches that could be updated without merges. But I'm on a crazy 
> > "everybody really wants detached HEAD and is needlessly scared" kick, and 
> > I'm probably reading too much into it.
> 
> Just to clarify: I didn't mean the question (which I didn't really
> understand) in this case, but the answer from Circuitsoft (second to
> last line). But maybe you also meant that? The question confuses me
> enough not to be able to follow.

Yeah. I think that Circuitsoft, and a lot of the people in these conversations, have local branches they never commit to, and only update with pull, and only use the --track feature to maintain these branches, and may not even ever use "git pull" for anything other than to maintain these branches. That would give the impression that "git pull" always leaves the current branch holding the commit that the remote branch is holding (i.e., "reset --hard") and the guess that this could apply to non-current branches.

But these local branches don't actually give the users any benefit, because they're always the same as the ref in remotes/ unless they're out-of-date.

Show 44 quoted lines
> > > 4) User expects "pull" to create branches
> > > 
> > > 07:25 	fynn 	Hey, I just pulled a branch from remote, and I don't see
> > > 		it in "git branch"
> > > 07:25 	doener 	fynn: if you "pull" that means "fetch this and merge it
> > > 		to what I have checked out"
> > > 07:25 	fynn 	doener: hm, I just did "git pull" and it showed the new
> > > 		branch
> > > 07:26 	fynn 	but I don't see it in my branches...
> > > 07:26 	fynn 	doener: should I create that branch as a tracking branch
> > > 		first?
> > > 07:26 	doener 	fynn: you're looking at "git branch -r" or "git branch
> > > 		-a", right?
> > > 07:26 	fynn 	doener: yeah, I'm seeing it in origin/foo, but not
> > > 		local.
> > > 07:26 	doener 	fynn: the "git fetch" should have created a remote
> > > 		tracking branch, as usual, not a local branch head
> > > 		(which would be shown by just "git branch")
> > > 07:27 	fynn 	doener: OK, what should I do to create it locally then?
> > > 07:28 	doener 	fynn: just the usual "git branch foo origin/foo", or to
> > > 		checkout at the same time: "git checkout -b foo
> > > 		origin/foo" or "git checkout -t origin/foo" (shortcut)
> > > 
> > > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-19#l830
> > > (Note how my "fetch this and merge it" is actually inaccurate for just
> > > "git pull", there is no "this" and that case. I took "pulled a branch"
> > > to mean that he did "git pull <remote> <branch>", which wouldn't have
> > > created/update the remote tracking branch [or did patches for that go
> > > in? I lost track...])
> > 
> > That sounds like a real converse of "push", including creating like-named 
> > local branches. Or, perhaps, this is someone expecting that "pull" is like 
> > "clone" in creating an initial local branch with the name and value of a 
> > specified remote branch.
> 
> Reading that one again, I realize that I've still been confused by the
> "pulled a branch". What happened was that the user did "git pull", which
> ran "git fetch <remote>", which fetched a new branch head and has shown
> that. At that point, the user (and me) got confused for maybe two reasons:
> 
> a) He didn't clearly distinguish between the fetch and the merge part.
> The new branch wasn't pulled, but just fetched. That caused the user to
> think that he "pulled the branch" (wrong terminology), which in term
> confused me (wrong use-case assumed).

Right; when pull shows a branch, it's the fetching step. But I think that shouldn't have been confusing to you; the merging step certainly doesn't show anything interesting.

Show 6 quoted lines
> b) He expected local branch heads to be created, instead of remote
> tracking branches. If my memory doesn't play tricks on me, that's
> actually not to be expected from that specific user (I think we told him
> about remote tracking branches before, and the last part of the
> conversation actually suggests that, too). If I don't forget, I'll try
> to get feedback from him the next time he's around.

He seems to get the thing about remote tracking branches (he says that got created); he's fine on the "pull = fetch + (X)" portion, but he's got (X) wrong, and thinks that creates a local branch.

That's why I think he may be confused by clone's behavior, because clone does: (create a repo), fetch something, and create a co-named local branch. If clone were init + pull (wrong, but a reasonable guess), then clone - init = fetch + checkout -b; so I think he's not totally lost but rather just wrong about what compound operations "pull" is.

Show 23 quoted lines
> > > 5) User possibly expecting "pull" to be able to act as "reset --hard"
> > > 
> > > 21:01 	aidan 	What do I do about this: html/config/core.php: needs
> > > 		update
> > > 21:02 	aidan 	git pull (gives that)
> > > 21:02 	Ilari 	aidan: You have uncommitted changes to that file...
> > > 21:15 	aidan 	Ilari: how can I just pull master and overwrite any
> > > 		changes?
> > > 
> > > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-18#l2130
> > > (I'm not sure about that one, "overwrite any changes" might mean "drop
> > > uncommitted changes and merge" or "just get me the remote's state,
> > > dropping my commits and uncommitted changes". Most of the time I've seen
> > > similar requests, the user wanted the latter).
> > 
> > So I think that's a desire for "git checkout ." first of all (with the 
> > assumption that the content without modifications has to come from 
> > somewhere remote). I don't know what's up with people not wanting to save 
> > their commits, though.
> 
> You haven't seen the multitude of "I have merge conflicts and just want
> to take theirs/mine" requests. That often gets more weird than just
> "drop my commits" ;-)

Ah, okay; I tend to think of those as content-focused, rather than history-focused. Like, I think people often run into: "I reformatted files A and B and made important changes to file A; someone else made important changes to file B; I get a awful merge conflict in file B." I bet it's common to want to keep your commit history, but throw away their conflicting changes in the resulting content.

There's also the occasional case where the right solution is to rename a branch to "things-that-seemed-like-a-good-idea-at-the-time", create a new branch from upstream with the old name, and never speak of it again.

But this is all a different topic.
Show 22 quoted lines
> > > 6) User says "pull" but probably means "fetch"
> > > 
> > > 14:08 	Alien_Freak 	once I have a clone of a repo I know you can do
> > > 			a checkout tag but is there anyway to pull just
> > > 			the tag?
> > > 
> > > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-16#l1664
> > > (There was no answer, thus it's hard to tell, but I guess he wanted
> > > something like:
> > > git init; git fetch --no-tags url tag <tag>; git checkout <tag>
> > > At least I'm quite sure he didn't mean "pull" as in "git pull")
> > 
> > I don't know; you can actually do:
> > 
> > $ git init; git pull --no-tags <url> tag <tag>
> > 
> > It updates the master branch and working directory from (nothing) to the 
> > fetched tag.
> 
> Hm, yeah, that works (didn't think of it), but it's a rather special
> case. Teaching that might lead to misunderstandings about what "pull"
> does, I think. It would look somewhat like "fetch + reset --hard".
Well, "merge" looks like "reset --hard" any time it's a fast forward.

I don't think this is a good thing to teach, but if the answer to what the user wants to do when saying "How can I just pull a tag in a single command" is "pull tag <foo>", it's hard to say that's a misuse of the term.

Show 18 quoted lines
> > > 8) "reset --hard" again
> > > 
> > > 20:10 	roger_padactor 	i commited then did a pull how do i get back to
> > > 			my commit. the pull over wrote the files
> > > 20:11 	merlin83 	roger_padactor: you can't, pull == fetch + hard
> > > 			reset to latest commit
> > > 
> > > http://colabti.de/irclogger/irclogger_log/git?date=2009-10-14#l2306
> > > (Someone being told that pull is fetch + reset --hard is actually new to
> > > me. Only saw that as an expectation previously.)
> > 
> > That's odd. How could you not notice that it doesn't actually do that, 
> > even if you try to get it to?
> 
> Hm? roger_padactor noticed that "pull" changed his files and wants to go
> back. And merlin83 says that that is impossible because pull supposedly
> does reset --hard. There's nothing in there (I could see) that suggests
> that anyone tried to make "pull" do "reset --hard".

I'm surprised that merlin83 can think that pull = fetch + reset --hard; people often seem to try to do fetch + reset --hard with pull, but it doesn't actually work for them.

Show 23 quoted lines
> merlin83 basically made three mistakes, I think:
> 1) Assume that roger_padactor was talking about uncommitted changes
> 2) Assume that pull is fetch + reset --hard
> 3) Assume that you can't undo a reset --hard for committed changes
> 
> (OK, 3) isn't actually valid when you consider 1), but 1) is so invalid
> that I kept 3). After all, "pull" would complain about a dirty tree...)
> 
> 
> > Actually, I wonder if the right formula is update = fetch + checkout. 
> > There are a lot of people (IMHO) want "git fetch origin; git checkout 
> > origin/master", and I think their first idea is "git update", but that 
> > doesn't exist, and they find "pull" as the closest thing.
> 
> That has a precondition that the user is already using a detached HEAD.
> Otherwise that fetch + checkout would likely mean that the get baffled
> when they do:
> git checkout master
> git update
> git checkout foo
> git checkout master
> 
> Seeing that "master" is out of date "again".
Agreed; I think:

$ git checkout master $ git update You are on a local branch. Local branches are under your complete control, so there is nowhere to get updates from. If you would like to merge remote commits into your local branch, you could use "git pull". If you would rather look at a remote branch, you could use "git checkout <some plausible remote branch>".

Of course, without this message:

$ git checkout master $ git update

would be the same as:

$ git chekcout master $ git fetch $ git checkout master

which would already not show any changes. (I'm thinking of the target of the checkout in update-with-no-target as being whatever you typed last time, and the fetch being whatever fetch normally updates that target.)

Personally, I often run:
$ git fetch; git checkout origin/next
This suggests that this is a useful combination of commands.
Show 7 quoted lines
> I agree though, that users might look for "git update" and because it is
> missing, they just look for the closest thing. Adding Junio's statement
> that users seem to want recipes instead of flexibility (and seeing
> "update" as just "get me new stuff from upstream" without meaning any
> specific method of updating), I think that "git update" could be a "recipe
> collection" tool. I'll hack that into my proof-of-concept thing (which
> I hope to have ready for a RFC next week).
I'll be interested to see that.
	-Daniel
*This .sig left intentionally blank*
Junio C Hamano· Oct 21, 2009, 06:22 UTC · re: Björn Steinbrink · lore

Re: [RFC] pull/fetch rename

Björn Steinbrink <B.Steinbrink@gmx.de> writes:
> So that's ten days of #git. I left out a bunch of duplications (most
> were "pull == fetch", "pull == update" and "pull to update
> non-checked-out branch").

Interesting; this shows that people who do not understand what "pull" does expect different behaviour from "pull", use the word "pull" to express what they want to happen, expect other people interpret the word to mean the way they think it does. At the same time, judging from different behaviour expected by these people, push/pull asymmetry does not seem to have much to do with the confusion. If the verb used by people who know git to call this operation were "distim", these people would also say "distim" and expect different things from it. I would foresee exactly the same problem if the verb were "update" for that matter.

It is just natural, as everybody learns a new language by listening how others talk and by imitating them.

Another thing I noticed while lurning on the #git channel for the past few days is that too much flexibility actually hurts new people. They do not want flexibility, but want to follow a set recipe. It just overwhelms to get too much flexibility upfront without enough guidance.

And there are too much historical flexibility that remain merely for historical reasons. We more or less killed the concept of separate object store and $GIT_DIR (i.e.one objects/ directory shared between more than one .git/ directories) when we made receive-pack aware of alternate repository information---it used to be that objects/ directory did not belong to a single set of refs/ hierarchy, but now it does and the receiving end of "git push" uses that knowledge to tell the sender what not to send in order to minimize the transfer. We will be gradually killing other kinds of historical flexibility that do not buy much in practice anymore, and that would reduce the issue of overwhelming flexibility.

For example, I am in favor of deprecating the "pull $there $src:$dst" notation. Before we standardized on the separate remote layout, it was sometimes handy to be able to use $dst that is a local branch, but these days, especially when repository $there has remote.$there.fetch mapping configured so that we can compute from $src what remote tracking branch we should store the fetched commit, the flexibility is more confusing than it is useful. "pull $there $src" (and "pull $there $src1 $src2" to build an octopus) should stay, but even there, it probably is a good idea for these notations to start updating remote tracking branches for $src ($src1 and $src2 in the octopus case) if the repository is configured to track them anyway, to match what "pull $there" that uses the default configuration does.

I am actually even Ok, at least in the long run (like in 3 years), if we were to deprecate the refspecs with colon given on the command line to "pull" and "fetch" altogether [*1*]. The rule will become "if you are going to use tracking branches to store what you fetch, you _must_ always have the tracking mapping defined in remote.$there.fetch configuration, and the location where one particular branch from the remote is stored is always determined by that mapping." It robs us the flexibility to fetch my 'next' and store it to your 'next' branch today and to your 'mext' branch tomorrow, and instead you would need to first fetch and then do an explicit "git branch mext origin/next" if you really want to do so, but I think the flexibility outlived its usefulness --- the primary value of these kinds of flexibility is to experiment with various workflows and UI concepts they allow, but I think we have gained enough experience to start judging what works (and is useful) and what doesn't (and is Ok to make it much more cumbersome to make or even impossible to do).

[Footnote]

*1* Except perhaps when deleting branches from the remote with "push", but even there we _could_ force people to do a deleting push separate from normal push and say "push --delete $there $this $and $that".

Clemens Buchacher· Oct 21, 2009, 17:19 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

On Tue, Oct 20, 2009 at 11:22:16PM -0700, Junio C Hamano wrote:
Show 7 quoted lines
> For example, I am in favor of deprecating the "pull $there $src:$dst"
> notation.  Before we standardized on the separate remote layout, it was
> sometimes handy to be able to use $dst that is a local branch, but these
> days, especially when repository $there has remote.$there.fetch mapping
> configured so that we can compute from $src what remote tracking branch we
> should store the fetched commit, the flexibility is more confusing than it
> is useful.

I emphatically agree. I was always uncomfortable with the refspec syntax, because it is too flexible. Why would I ever want to access branch refs other than refs/heads/ on the remote, and why would I ever want to write directly to the local refs/heads/ namespace (in a non-bare repo), as opposed to refs/remotes/<name>? Unless he wants to do something unusual, the user should not be confronted with questions like that.

Clemens
Clemens Buchacher· Oct 21, 2009, 17:21 UTC · re: Junio C Hamano · lore

[PATCH] modernize fetch/merge/pull examples

The "git pull" documentation has examples which follow an outdated style. Update the examples to use "git merge" where appropriate and move the examples to the corresponding manpages.

Furthermore,
 o show that pull is equivalent to fetch and merge, which is still a
   frequently asked question,
 o explain the default fetch refspec.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
---
On Tue, Oct 20, 2009 at 11:22:16PM -0700, Junio C Hamano wrote:
> For example, I am in favor of deprecating the "pull $there $src:$dst"
> notation. 
A first step in that direction.
Clemens
 Documentation/git-fetch.txt |   29 +++++++++++++++++++++++++
 Documentation/git-merge.txt |   33 +++++++++++++++++++++++++++++
 Documentation/git-pull.txt  |   49 +++---------------------------------------
 3 files changed, 66 insertions(+), 45 deletions(-)
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index d3164c5..c76077d 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -37,6 +37,35 @@ include::pull-fetch-param.txt[]
 
 include::urls-remotes.txt[]
 
+
+EXAMPLES
+--------
+
+* Update the remote-tracking branches:
++
+------------------------------------------------
+$ git fetch origin
+------------------------------------------------
++
+The above command copies all branches from the remote refs/heads/
+namespace and stores them to the local refs/remotes/origin/ namespace,
+unless the branch.<name>.fetch option is used to specify a non-default
+refspec.
+
+* Using refspecs explicitly:
++
+------------------------------------------------
+$ git fetch origin +pu:pu maint:tmp
+------------------------------------------------
++
+This updates (or creates, as necessary) branches `pu` and `tmp` in
+the local repository by fetching from the branches (respectively)
+`pu` and `maint` from the remote repository.
++
+The `pu` branch will be updated even if it is does not fast-forward;
+the others will not be.
+
+
 SEE ALSO
 --------
 linkgit:git-pull[1]
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index d05f324..2a41d62 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -212,6 +212,39 @@ You can work through the conflict with a number of tools:
    common ancestor, 'git show :2:filename' shows the HEAD
    version and 'git show :3:filename' shows the remote version.
 
+
+EXAMPLES
+--------
+
+* Bundle branches `fixes` and `enhancements` on top of
+  the current branch, making an Octopus merge:
++
+------------------------------------------------
+$ git merge fixes enhancements
+------------------------------------------------
+
+* Merge branch `obsolete` into the current branch, using `ours`
+  merge strategy:
++
+------------------------------------------------
+$ git merge -s ours obsolete
+------------------------------------------------
+
+* Merge branch `maint` into the current branch, but do not make
+  a commit automatically:
++
+------------------------------------------------
+$ git merge --no-commit maint
+------------------------------------------------
++
+This can be used when you want to include further changes to the
+merge, or want to write your own merge commit message.
++
+You should refrain from abusing this option to sneak substantial
+changes into a merge commit.  Small fixups like bumping
+release/version name would be acceptable.
+
+
 SEE ALSO
 --------
 linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index 7578623..de2bcd6 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -131,54 +131,13 @@ $ git pull origin next
 ------------------------------------------------
 +
 This leaves a copy of `next` temporarily in FETCH_HEAD, but
-does not update any remote-tracking branches.
-
-* Bundle local branch `fixes` and `enhancements` on top of
-  the current branch, making an Octopus merge:
-+
-------------------------------------------------
-$ git pull . fixes enhancements
-------------------------------------------------
-+
-This `git pull .` syntax is equivalent to `git merge`.
-
-* Merge local branch `obsolete` into the current branch, using `ours`
-  merge strategy:
-+
-------------------------------------------------
-$ git pull -s ours . obsolete
-------------------------------------------------
-
-* Merge local branch `maint` into the current branch, but do not make
-  a commit automatically:
+does not update any remote-tracking branches. Using remote-tracking
+branches, the same can be done by invoking fetch and merge:
 +
 ------------------------------------------------
-$ git pull --no-commit . maint
+$ git fetch origin
+$ git merge origin/next
 ------------------------------------------------
-+
-This can be used when you want to include further changes to the
-merge, or want to write your own merge commit message.
-+
-You should refrain from abusing this option to sneak substantial
-changes into a merge commit.  Small fixups like bumping
-release/version name would be acceptable.
-
-* Command line pull of multiple branches from one repository:
-+
-------------------------------------------------
-$ git checkout master
-$ git fetch origin +pu:pu maint:tmp
-$ git pull . tmp
-------------------------------------------------
-+
-This updates (or creates, as necessary) branches `pu` and `tmp` in
-the local repository by fetching from the branches (respectively)
-`pu` and `maint` from the remote repository.
-+
-The `pu` branch will be updated even if it is does not fast-forward;
-the others will not be.
-+
-The final command then merges the newly fetched `tmp` into master.
 
 
 If you tried a pull which resulted in a complex conflicts and
-- 
1.6.5.1
Junio C Hamano· Oct 21, 2009, 21:38 UTC · re: Clemens Buchacher · lore

Re: [PATCH] modernize fetch/merge/pull examples

Clemens Buchacher <drizzd@aon.at> writes:
> The "git pull" documentation has examples which follow an outdated
> style. Update the examples to use "git merge" where appropriate and
> move the examples to the corresponding manpages.
Makes sense, although I did some minor rewording.

I noticed something related while reading this (the issue does not affect the validity of this patch).

Show 9 quoted lines
> +* Merge branch `maint` into the current branch, but do not make
> +  a commit automatically:
> ++
> +------------------------------------------------
> +$ git merge --no-commit maint
> +------------------------------------------------
> ++
> +This can be used when you want to include further changes to the
> +merge, or want to write your own merge commit message.

When you are up to date with maint this would be a no-op, and when you are strictly behind maint it will succeed without creating a new commit.

I have two possible approaches to fix this issue.
Junio C Hamano· Oct 21, 2009, 21:41 UTC · re: Junio C Hamano · lore

[RFC/PATCH] git-merge: forbid fast-forward and up-to-date when --no-commit is given

Traditionally "git merge --no-commit" meant just that: do not create a new commit even when a merge succeeds. But this leads to confusion when the merged commit is a descendant of the current commit, in which case we succeed the merge by fast-forwarding and without creating a new commit. Also when the merged commit is already a part of the history, we succeeded without doing anything.

Error out when --no-commit is given but the merge would result in a fast-forward or an up-to-date.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * This is the first alternative.  I think it makes more sense than the
   other one, but I am unsure, as I obviously do not get confused when
   --no-commit becomes no-op due to a fast-forward nor an up-to-date and
   am rather happy with the current behaviour.
 builtin-merge.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/builtin-merge.c b/builtin-merge.c
index b6b8428..4cfdf75 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -829,6 +829,12 @@ static int evaluate_result(void)
 	return cnt;
 }
 
+static void check_no_commit(const char *msg)
+{
+	if (!option_commit)
+		die("The merge will %s but --no-commit was given.", msg);
+}
+
 int cmd_merge(int argc, const char **argv, const char *prefix)
 {
 	unsigned char result_tree[20];
@@ -996,6 +1002,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		 * If head can reach all the merge then we are up to date.
 		 * but first the most common case of merging one remote.
 		 */
+		check_no_commit("be a no-op because you are up-to-date");
 		finish_up_to_date("Already up-to-date.");
 		return 0;
 	} else if (allow_fast_forward && !remoteheads->next &&
@@ -1006,6 +1013,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		struct object *o;
 		char hex[41];
 
+		if (allow_fast_forward)
+			check_no_commit("fast forward");
+
 		strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
 
 		if (verbosity >= 0)
@@ -1074,6 +1084,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			}
 		}
 		if (up_to_date) {
+			check_no_commit("fast forward");
 			finish_up_to_date("Already up-to-date. Yeeah!");
 			return 0;
 		}
-- 
1.6.5.1.107.gba912
Nanako Shiraishi· Oct 22, 2009, 10:21 UTC · re: Junio C Hamano · lore

Re: [RFC/PATCH] git-merge: forbid fast-forward and up-to-date when --no-commit is given

Quoting Junio C Hamano <gitster@pobox.com>
Show 17 quoted lines
> Traditionally "git merge --no-commit" meant just that: do not create a new
> commit even when a merge succeeds.  But this leads to confusion when the
> merged commit is a descendant of the current commit, in which case we
> succeed the merge by fast-forwarding and without creating a new commit.
> Also when the merged commit is already a part of the history, we succeeded
> without doing anything.
>
> Error out when --no-commit is given but the merge would result in a
> fast-forward or an up-to-date.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>
>  * This is the first alternative.  I think it makes more sense than the
>    other one, but I am unsure, as I obviously do not get confused when
>    --no-commit becomes no-op due to a fast-forward nor an up-to-date and
>    am rather happy with the current behaviour.

I think this is good (but I am saying this only from your description without understanding the updated code), but the change breaks --squash to merge a branch, doesn't it?

    % git checkout feature  # from your master branch
    % work; git commit; work; git commit
    % git checkout master  # go back to your master branch
    % git merge --squash feature

This is a useful way to clean up changes that were built in small steps that turned out to be worth only a commit.

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
Junio C Hamano· Oct 22, 2009, 22:26 UTC · re: Nanako Shiraishi · lore

Re: [RFC/PATCH] git-merge: forbid fast-forward and up-to-date when --no-commit is given

Nanako Shiraishi <nanako3@lavabit.com> writes:
Show 9 quoted lines
> the change breaks --squash to merge a branch, doesn't it?
>
>     % git checkout feature  # from your master branch
>     % work; git commit; work; git commit
>     % git checkout master  # go back to your master branch
>     % git merge --squash feature
>
> This is a useful way to clean up changes that were built
> in small steps that turned out to be worth only a commit.

Incidentally we seemed to have seen an end user request for exactly this workflow.

A reroll has been queued, as below, with an update to a test script that expects --no-commit to be a no-op for fast-forward.

-- >8 --

Traditionally "git merge --no-commit" meant just that: do not create a new commit even when a merge succeeds. But this leads to confusion when the merged commit is a descendant of the current commit, in which case we succeed the merge by fast-forwarding and without creating a new commit.

Also when the merged commit is already a part of the history, we succeeded without doing anything.

Error out when --no-commit is given but the merge would result in a fast-forward or an up-to-date.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-merge.c  |   11 +++++++++++
 t/t7600-merge.sh |    4 +---
 2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/builtin-merge.c b/builtin-merge.c
index b6b8428..2149aed 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -829,6 +829,12 @@ static int evaluate_result(void)
 	return cnt;
 }
 
+static void check_no_commit(const char *msg)
+{
+	if (!option_commit)
+		die("The merge will %s but --no-commit was given.", msg);
+}
+
 int cmd_merge(int argc, const char **argv, const char *prefix)
 {
 	unsigned char result_tree[20];
@@ -996,6 +1002,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		 * If head can reach all the merge then we are up to date.
 		 * but first the most common case of merging one remote.
 		 */
+		check_no_commit("be a no-op because you are up-to-date");
 		finish_up_to_date("Already up-to-date.");
 		return 0;
 	} else if (allow_fast_forward && !remoteheads->next &&
@@ -1006,6 +1013,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		struct object *o;
 		char hex[41];
 
+		if (allow_fast_forward && !squash)
+			check_no_commit("fast forward");
+
 		strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
 
 		if (verbosity >= 0)
@@ -1074,6 +1084,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			}
 		}
 		if (up_to_date) {
+			check_no_commit("be a no-op because you are up-to-date");
 			finish_up_to_date("Already up-to-date. Yeeah!");
 			return 0;
 		}
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index e5b210b..86b0537 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -265,9 +265,7 @@ test_debug 'gitk --all'
 
 test_expect_success 'merge c0 with c1 (no-commit)' '
 	git reset --hard c0 &&
-	git merge --no-commit c1 &&
-	verify_merge file result.1 &&
-	verify_head $c1
+	test_must_fail git merge --no-commit c1
 '
 
 test_debug 'gitk --all'
-- 
1.6.5.1.124.g746fb6
Junio C Hamano· Oct 21, 2009, 21:46 UTC · re: Junio C Hamano · lore

[PATCH] git-merge: imply --no-ff when --no-commit is given

Traditionally "git merge --no-commit" meant just that: do not create a new commit even when a merge succeeds. But this leads to confusion when the merged commit is a descendant of the current commit, in which case we succeed the merge by fast-forwarding and without creating a new commit.

Make --no-commit imply --no-ff; --no-commit is a request by the user to tweak the resulting merge and it is clear indication that the user wants to have a merge, even if it is an extra one, to futz with.

There is a test that relies on --no-commit silently fast forwarding; that is obviously broken by this change.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * This is another possibility, which I think is worse than the other one
   in practice but the justification sounds more respectable.
   Unlike the other one, this will still make --no-commit a no-op when you
   are already up-to-date.  As I do not think --no-ff makes much sense in
   my own workflow (either here or dayjob) it is not exactly my itch, but
   I suspect that people who wanted to have --no-ff may want to create an
   extra commit even in such a case; it may be a bug to allow up-to-date
   when --no-ff is given.  Yes, it would make the --no-ff even more insane
   than it already is, but I suspect it would be more consistent with the
   original reasoning of wanting to have the option in the first place,
   namely, to leave the trace of the fact that a "merge" was done at that
   point in the history.
 builtin-merge.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/builtin-merge.c b/builtin-merge.c
index b6b8428..fa86799 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -874,6 +874,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		option_commit = 0;
 	}
 
+	if (!option_commit)
+		allow_fast_forward = 0;
+
 	if (!argc)
 		usage_with_options(builtin_merge_usage,
 			builtin_merge_options);
-- 
1.6.5.1.107.gba912
Clemens Buchacher· Oct 22, 2009, 06:35 UTC · re: Junio C Hamano · lore

Re: [PATCH] git-merge: imply --no-ff when --no-commit is given

On Wed, Oct 21, 2009 at 02:46:50PM -0700, Junio C Hamano wrote:
> Make --no-commit imply --no-ff; --no-commit is a request by the user to
> tweak the resulting merge and it is clear indication that the user wants
> to have a merge, even if it is an extra one, to futz with.

I think --no-commit makes sense in case of a real merge, because a 3-way diff can help fix any semantic errors. Apart from that, one can simply do a regular merge and --amend it later.

In case of a fast-forward merge, there is not going to be a 3-way diff anyways. So it's pointless to use --no-commit in this case.

I'm therefore in favor of your other proposal, even though it may be confusing to users who don't understand the difference between n-way and fast-forward merge. But that's something they will have to learn.

And --no-ff can always be used explicitly.
Clemens
Thomas Rast· Oct 22, 2009, 08:51 UTC · re: Clemens Buchacher · lore

Re: [PATCH] modernize fetch/merge/pull examples

Clemens Buchacher wrote:
Show 6 quoted lines
> On Tue, Oct 20, 2009 at 11:22:16PM -0700, Junio C Hamano wrote:
> 
> > For example, I am in favor of deprecating the "pull $there $src:$dst"
> > notation. 
> 
> A first step in that direction.
I think this is a good change independently of the deprecation.
> +------------------------------------------------
> +$ git fetch origin +pu:pu maint:tmp
> +------------------------------------------------
[...]
> +The `pu` branch will be updated even if it is does not fast-forward;
> +the others will not be.

I think to a new user it is not immediately clear if this means "will not be updated, period" or "will not be updated if ...". How about

  The `pu` branch will always be updated; the `tmp` branch only if it
  is a fast-forward update.
-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Thomas Rast· Oct 22, 2009, 09:48 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

Junio C Hamano wrote:
Show 12 quoted lines
> Björn Steinbrink <B.Steinbrink@gmx.de> writes:
> 
> > So that's ten days of #git. I left out a bunch of duplications (most
> > were "pull == fetch", "pull == update" and "pull to update
> > non-checked-out branch").
> 
> Interesting; this shows that people who do not understand what "pull" does
> expect different behaviour from "pull", use the word "pull" to express
> what they want to happen, expect other people interpret the word to mean
> the way they think it does.  At the same time, judging from different
> behaviour expected by these people, push/pull asymmetry does not seem to
> have much to do with the confusion.

This of course is where our conclusions differ. I haven't counted them, but Björn (thanks again for the excellent survey) points out that most duplicates are confusion with fetch, (imagined) update or "update to not checked out branch".

Pull is none of these, but if it was (current) fetch, at least the first group of people would have had the right idea of what it does.

> I am actually even Ok, at least in the long run (like in 3 years), if we
> were to deprecate the refspecs with colon given on the command line to
> "pull" and "fetch" altogether [*1*].

As an aside, there are actually some use-cases, e.g., to grab the git-svn refs from a freshly cloned repository you would run:

  git fetch origin refs/remotes/*:refs/remotes/*

(and then 'git svn init' etc.) I've also had some weird requests on IRC that could be solved by clever (and of course dangerous) use of 'git fetch . glob:otherglob'.

Hiding that power behind an option could be a good idea though.
-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Mike Hommey· Oct 21, 2009, 06:30 UTC · re: Daniel Barkalow · lore

Re: [RFC] pull/fetch rename

On Tue, Oct 20, 2009 at 07:56:01PM -0400, Daniel Barkalow wrote:
Show 17 quoted lines
> On Tue, 20 Oct 2009, Thomas Rast wrote:
> 
> > Hi all,
> > 
> > While everyone is busy in two other UI threads, I figured I might as
> > well toss up another (probably) controversial topic.
> > 
> > Especially on IRC, we see many people who are some combination of
> > misunderstanding, misusing or overusing git-pull.  I figure this is
> > the result of several factors, notably
> > 
> > a) pull/push are not symmetric,
> 
> In a certain sense they are; they both update the branches local to one 
> repository with the data from the other repository. In this sense, fetch 
> is the oddity in that it doesn't update any repository's own branches, but 
> just the local information about other repositories' branches.

BTW, shouldn't fetch be deprecated in favour of git remote update ? (this may require adding some features to git remote update, but you get the idea)

Mike
Junio C Hamano· Oct 21, 2009, 06:33 UTC · re: Mike Hommey · lore

Re: [RFC] pull/fetch rename

Mike Hommey <mh@glandium.org> writes:
> BTW, shouldn't fetch be deprecated in favour of git remote update ?

Why? People will then be confused because half of them would expect "remote update" to somehow affect their working tree, and some others would expect their working tree reset to one of the branches from the remote, and it won't solve anything. Oh, and it will irritate people who are used to type "git fetch", too.

Mike Hommey· Oct 21, 2009, 07:06 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

On Tue, Oct 20, 2009 at 11:33:40PM -0700, Junio C Hamano wrote:
Show 8 quoted lines
> Mike Hommey <mh@glandium.org> writes:
> 
> > BTW, shouldn't fetch be deprecated in favour of git remote update ?
> 
> Why?  People will then be confused because half of them would expect
> "remote update" to somehow affect their working tree, and some others
> would expect their working tree reset to one of the branches from the
> remote, and it won't solve anything.

I must be missing the obvious but which one of fetch and remote update does the above ? I was under the impression that none of them would.

> Oh, and it will irritate people who
> are used to type "git fetch", too.

That's another problem, but my understanding is that git fetch and git remote update are roughly doing the same thing. Having two commands for the same thing is confusing. I kind of like the idea to have one command, remote, to handle, err, remotes. Also note that I said deprecated, not remove ; that could mean keeping fetch, but pushing the use of remote update for new users.

Mike
Junio C Hamano· Oct 21, 2009, 07:22 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

Junio C Hamano <gitster@pobox.com> writes:
Show 9 quoted lines
> Mike Hommey <mh@glandium.org> writes:
>
>> BTW, shouldn't fetch be deprecated in favour of git remote update ?
>
> Why?  People will then be confused because half of them would expect
> "remote update" to somehow affect their working tree, and some others
> would expect their working tree reset to one of the branches from the
> remote, and it won't solve anything.  Oh, and it will irritate people who
> are used to type "git fetch", too.

I think the above comment needs to be clarified, so that I will not discourage you or other people who would want to pursue the part I omitted from my quote too much, which was:

> (this may require adding some features to git remote update, but you get
> the idea)

Now, I _personally_ think "git remote update" was a half-baked UI experiment that failed, but as the maintainer I'll still give it benefit of doubt for a bit longer and let interested parties resurrect and perfect it, just in case it might turn out to be a good thing. In the rest, when I say "I think", pretend as if I said _personally_ (i.e. not speaking as the maintainer who already has given up on it).

I think the original "git remote add" was a good interface, similar to "git config", as the management interface to the remote system used by the everyday commands "fetch/pull/push". The everyday commands use the remote nicknames and their associated data stored in the configuration file.

While you can edit your configuration file directly to manage the remotes, some people (and recipe book writers) prefer to have a specialized management command. "git remote add" is such a management interface that you use once and then you can forget about it. Once you get your remote configured, the everyday commands will use the data in the configuration file, and the commands you interract with your remotes will be these everyday commands, not "git remote".

Some people thought that throwing everything that does something to remote under "git remote" was a good idea, and "git remote update" was invented. It is a thin wrapper around "fetch" and does what "fetch" does. You need to understand "fetch" (i.e. downloads the history and necessary objects, and updates the remote tracking branches, without ever touching the work tree) to understand "git remote update" anyway, and more importantly, you need to understand what they do not do.

It is not even a typesaver. "git fetch" updates from the default remote, so does "git remote update". Personally I think the people who invented "git remote update" were misguided, and that is why I say it was a failed UI experiment that failed, but that is hindsight talking [*1*].

After reading Björn's excerpts, it was clear to me that the names of the commands have much less to do with the confusion [*2*] than I originally feared [*3*]. As long as the user needs the same kind of understanding of what the command does, I do not think changing the command name between "git remote update" vs "git fetch" and calling everything that has something to do with remote repositories "remote" would solve anything. The users also need to understand how to make what these commands do an integrated part in a larger workflow they use, so that they know what to do next, which is much more important issue, and at that point the name of the command is secondary---the concepts counts much more.

"git remote update" even has a slight downside in the "push moves from here to there, pull moves from there to here" sense. If you never have seen git, "git remote update $there" may look like you are asking git to update the remote called $there, presumably with what you have. That is quite opposite direction from how it actually move things.

[Footnote]

*1* The only thing "git remote update" does that "git fetch" does not is that it can serve as "fetch from everywhere" shorthand. But that is something we could have added to "git fetch". So in that sense, I think it may make even more sense to deprecate "remote update" and teach "fetch" how to do that.

*2* Granted, if our "pull" were named "push", the natural meaning of the word "push" that moves things from here to there (as opposed to there to here) may even confuse people, but both "pull" and "fetch" mean moving things from farther to closer (and nothing more in the natural meaning), and the confusion expressed in the thread were not of that kind---nobody expected us to do anything that involves moving something we have to the remote, but the confusion was about what happens _after_ something was moved from there to here.

*3* In a sense I somehow was hoping that the confusion was only about the push/pull asymmetry as some people claimed. If it were, the problem would have been very easy to fix; you just do not let pull affect the work tree. But the confused users were expecting the changes to be reflected to their work trees, and the confusion was about how that is done. Some wanted their local changes blown away, some wanted their local histories also get blown away, some wanted the changes integrated.

Jeff King· Oct 21, 2009, 07:45 UTC · re: Junio C Hamano · lore

Re: [RFC] pull/fetch rename

On Wed, Oct 21, 2009 at 12:22:35AM -0700, Junio C Hamano wrote:
Show 12 quoted lines
> Some people thought that throwing everything that does something to remote
> under "git remote" was a good idea, and "git remote update" was invented.
> It is a thin wrapper around "fetch" and does what "fetch" does.  You need
> to understand "fetch" (i.e. downloads the history and necessary objects,
> and updates the remote tracking branches, without ever touching the work
> tree) to understand "git remote update" anyway, and more importantly, you
> need to understand what they do not do.
> 
> It is not even a typesaver.  "git fetch" updates from the default remote,
> so does "git remote update".  Personally I think the people who invented
> "git remote update" were misguided, and that is why I say it was a failed
> UI experiment that failed, but that is hindsight talking [*1*].

Declaring it a failure depends on what you consider the goal of "git remote update" to be. I find it very useful as a shorthand for "fetch from _all_ remotes"[1]. Which does save typing over

  $ for i in `git remote`; do git fetch $i; done

And of course, there is "git remote" again, saving us a few keystrokes over:

  $ git config --get-regexp 'remote..*.url' | cut -d. -f2

[1]: And I think this is a useful operation. When collaborating with developers in multiple repositories, it is nice to see an overview of what all other people are working on. We have other tools to actually compare the refs, but the first step is obviously getting those refs up to date locally.

-Peff
Jeff King· Oct 21, 2009, 07:47 UTC · re: Jeff King · lore

Re: [RFC] pull/fetch rename

On Wed, Oct 21, 2009 at 03:45:22AM -0400, Jeff King wrote:
Show 13 quoted lines
> Declaring it a failure depends on what you consider the goal of "git
> remote update" to be. I find it very useful as a shorthand for "fetch
> from _all_ remotes"[1]. Which does save typing over
>
> [...]
>
> On Wed, Oct 21, 2009 at 12:22:35AM -0700, Junio C Hamano wrote:
>
>> *1* The only thing "git remote update" does that "git fetch" does not
>> is that it can serve as "fetch from everywhere" shorthand.  But that
>> is something we could have added to "git fetch".  So in that sense, I
>> think it may make even more sense to deprecate "remote update" and
>> teach "fetch" how to do that.

...and it would probably help if I had read your footnotes before responding.

-Peff
Junio C Hamano· Oct 24, 2009, 06:30 UTC · re: Jeff King · lore

Re: [RFC] pull/fetch rename

Jeff King <peff@peff.net> writes:
Show 12 quoted lines
> On Wed, Oct 21, 2009 at 12:22:35AM -0700, Junio C Hamano wrote:
>
>> It is not even a typesaver.  "git fetch" updates from the default remote,
>> so does "git remote update".  Personally I think the people who invented
>> "git remote update" were misguided, and that is why I say it was a failed
>> UI experiment that failed, but that is hindsight talking [*1*].
>
> Declaring it a failure depends on what you consider the goal of "git
> remote update" to be. I find it very useful as a shorthand for "fetch
> from _all_ remotes"[1]. Which does save typing over
>
>   $ for i in `git remote`; do git fetch $i; done

You've since read my footnote about "git fetch <group>", so I do not think this part is controversial anymore.

> And of course, there is "git remote" again, saving us a few keystrokes
> over:
>
>   $ git config --get-regexp 'remote..*.url' | cut -d. -f2
And as you may have already realized by now, I was saying two things.
 (1) "git remote" in general is a good management interface for remote
     nicknames and attributes attached to them, in the similar spirit as
     "git config" is a good management interface for the underlying
     configuration files.
 (2) "git remote update" is a misguided UI expariment that failed.

So there is no disagreement between us on the "and of course" part, either.

← back to recent threads