On Monday 14 February 2011, Junio C Hamano wrote: > Johan Herland <johan@xxxxxxxxxxx> writes: > > Yes, replicating existing behavior w/explicit refspecs would look like: > > [remote "origin"] > > > > url = git://git.example.com/repo.git > > fetch = +HEAD:refs/remotes/origin/HEAD > > fetch = +refs/heads/*:refs/remotes/origin/* > > fetch = ~refs/tags/*:refs/tags/* > > While this is fine, I am not sure about the "HEAD" part. Most of the > protocol do not convey which branch HEAD points at (instead "clone" has > to guess), which eventually needs to be fixed. Incremental updates via > "fetch" does not touch "HEAD" at all by design; unlike the real branch > heads "remotes/origin/$branch" that are used to keep copies of what are > at the remote, "remotes/origin/HEAD" is meant to be used by the local > repository to designate which of the remote branch is considered the > primary branch from local repository owner's point of view, primarily so > that you can say "origin" locally to mean "origin/next" by setting the > symref origin/HEAD to point at it. In that sense, the guess made by > "clone" is only used to give an initial value. Ah, ok. I've misunderstood the purpose of "remotes/origin/HEAD" then. Feel free to remove that refspec line from my proposal, and leave it as a special-purpose thing set up by clone (and maintained by the user thereafter). Still (as I think was recently discussed in another thread), the existence of remotes/origin/HEAD _does_ cause problems if the origin remote also has a branch called "refs/heads/HEAD" (which would collide when fetched into the local repo). > > FTR, my new/proposed refspecs would look like this: > > [remote "origin"] > > > > url = git://git.example.com/repo.git > > fetch = +HEAD:refs/remotes/origin/HEAD > > fetch = +refs/heads/*:refs/remotes/origin/heads* > > fetch = ~+refs/tags/*:refs/remotes/origin/tags/* > > > > ( fetch = +refs/notes/*:refs/remotes/origin/notes/* ) > > ( fetch = +refs/replace/*:refs/remotes/origin/replace/* ) > > I think you meant "refs/remotes/origin/heads/*" (note the slash) on the > RHS of the branch refspecs. Indeed. Thanks for pointing out the typo. > How's that different from refs/*:refs/remotes/origin/* by the way? It's not, except that "refs/*:refs/remotes/origin/*" would fetch a too-large superset. E.g. it would fetch "refs/remotes/third-party/heads/foo" into "refs/remotes/origin/remotes/third-party/heads/foo", which we probably don't want. > Also > if you give tags a totally separate namespace, I don't see much reason to > still give it the "auto-follow" semantics. It is far simpler to explain > if you just fetch all of them and be done with it, no? Agreed. Also, to quote Peff in http://thread.gmane.org/gmane.comp.version- control.git/160503/focus=160726 : "Now you could argue that auto-follow is not worth the effort. It is somewhat confusing, and I can't think of a time when it ever actually reduced the set of objects I was fetching (as opposed to just fetching all tags). But maybe others have use cases where it matters." So if nobody disagree, I would have no problem with dropping the leading "~" from the refspec, thus disabling auto-following (tracking all tags explicitly instead). > > Yes, to me it seems intuitive that when you specify <URL> (even if > > <URL> corresponds to an existing remote) you do NOT update > > remote-tracking refs, but if you use <remote>, you should ALWAYS > > update remote-tracking refs. Others may disagree. > > One argument for disagreement used to be that an explicit fetch of a > single branch was a deliberate way to avoid updating the tracking branch > before examining what has been changed (i.e. "git fetch origin master" > followed by "git log origin/master..FETCH_HEAD" and hopefully followed by > "git pull origin" or somesuch). But that was before reflog was adopted > as a reliable safety measure, and I don't think people should rely on > that behaviour anymore. > > I would actually make an even stronger point that people should not base > their workflow on keeping remote tracking refs deliberately stale, which > is exactly the "feature" was meant to be used for. What has happened on > the other end has already happened whether you like it or not, and there > is no point in your locally pretending that it didn't happen. If you > don't like the latest update there, you go talk to the party that control > the remote and rectify the situation with them. It may involve pushing a > reverting or correcting commit over there, or in the worst case you > simply stop pulling from them, forking the project in effect at that > point. Agreed. > > It may seem so, but in my experience it doesn't really work perfectly: > > Even if I fully control the repo I push to, I still want precise > > control over what I push there. Sometimes I may working on 'next' and > > 'master' in parallel, and I might have finished and tested some > > bugfixes on 'master', while I still have unfinished/untested stuff on > > 'next'. > > Yes, I do this all the time and I often say "git push ko maint master" > (ko is my name for the k.org repo). I however don't feel inconvenienced > by it precisely because when I make such a push, I _know_ that I want to > push only these two branches. Saying "only these two branches" > explicitly from the command line, and seeing only these two branches go > out, are very assuring to me. I usually try to be much more organized > to make sure all four integration branches satisfy certain preconditions > before pushing, and I say "git push ko" only after I make sure they do. > > I consider it is a good UI design to force myself to type more when I am > doing something un(der)disciplined and to let me type less when I am > following a good project hygiene. I don't doubt that the current behavior works well for you (otherwise I expect you would have changed it). However, what I've seen at $dayjob is that more inexperienced users will often push right after committing, and at that time they're still very much in the "working-on-one-branch" state of mind (as opposed to the "administering-multiple-branches" state of mind), so when they follow up a "git commit" with a "git push" they're surprised (or worse: oblivious) to the fact that "git push" can push multiple branches. I guess it comes down to whether you fundamentally consider "git push" something that pushes multiple _branches_, or something that pushes multiple _commits_. And for the latter of those groups push.default == "matching" is inherently more "dangerous" than for the former. (Granted, me telling everyone to use push.default == "tracking" probably doesn't help them in discovering "git push"'s ability to update multiple branches.) Have fun! :) ...Johan -- Johan Herland, <johan@xxxxxxxxxxx> www.herland.net -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html