There is a behavior of git-push that is the most annoying thing while working with a central-repository: `git push` without any arguments insists on pushing every local refspec that match one in origin. While it's perfectly correct when you push to a public repository (you do that seldom, and usually only after having prepared it with care), it's not true for the central-repository layout. At work, I often have this situation: [I'm in the devel branch, would be next for git e.g.] ... hack ... hack ... *OMG* what a nasty bug... $ git stash $ git checkout <stable branch> .. fix nasty bug .. $ git commit $ git push # so that co-workers have the fix asap $ git checkout <devel branch> $ git stash apply ... OOOOH NOES it pushed my WIP in my devel branch as well ... There has been (and still is atm) a quite heated discussion on IRC about that. Some arguments were that pull/push were opposite words in English, but weren't doing an opposite thing in git, which led to some fight. But that's not close to the point IMHO. The real question is "what does users intend when they `git push`". In a git/kernel/... like model, you don't think the same than in a svn/cvs-like model. I mean, Junio or Linus likely don't push a lot to their public repository. It happens probably a couple of time per day. While I'm at work, it happens up way more frequentely, and I then want to lazily type `git push` and not `git push origin <somebranch>`. it's too long. I'm not sure what we can do about it, but I'm pretty sure it bites a lot of people out there. For now I use this alias in my .gitconfig: p=3D!git-push origin `git-symbolic-ref HEAD` but still, it feels really wrong to me. Not to mention that git-push(1) says that it has a --all option that in fact is the current default behavior, hence sounds pretty useless. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO ...
The default is not --all but "matching branches", iow, what you have never published yet never goes out. Having said that, I would agree that in some workflows "I am on this branch and I would want to push only this branch" would be the norm, and the norm even be "and this branch 'foo' is called identically as 'foo' at the remote site as well". Don't worry about me when discussing to change the default. Myself, I also often push only one or two branches. A typical workflow for me while working on git.git is to prepare 'maint' (if there are any changes) and 'master', push them (without pushing 'next' and 'pu') to a private "build it to make sure" repository I have at a k.org machine which runs RH, make sure they are Ok, and then continue working on integrating 'next' and 'pu'. At the end of the day, I push out all four integration branches to a separate "publish" area, but even this one, I rely on the explicit configuration (remote.<name>.push) to push out only the integration branches and not other branches. We would also want to have --mirror option that acts like --all but removes the refs from the remote that do not exist anymore, so we will be talking about updating "git push" in the near future anyway. So what's the desired semantics? The current semantics is: "git push" says "you do not say to which repository?" and consults "branch.<current>.remote" but defaults to 'origin' if unconfigured. "git push <name>" (or using the <name> determined as above) says "you do not say which branches?" and consults "remote.<name>.push" to find branches to push out, but defaults to 'matching branches' if unconfigured. What you would want to change is the fallback behaviour for unconfigured "remote.<name>.push". I think it is sensible to have an option to make it push only the current branch. I am not sure if it is sensible to make that the default (and introduce --matching option to get the current behaviour) ...
I really like the current default, it matches my mental model well: I generally use "push" to mean "synchronize the remote repository with my current one"; if multiple branches have changed, I want those changes propagated too. I think changing it would be a bad idea, it just seems a pointlessly incompatible change. The reasons I've seen offered on this thread for changing the default seem pretty weak, e.g., "it's more conservative" (but more annoying), and "it's more like SVK" (who cares?). -Miles -- Freedom's just another word, for nothing left to lose --Janis Joplin -
I understand that =E2=80=A6 and I know some people rely on the current There definitely is a point: with the current behaviour you sometimes end up pushing more than what you meant, with sometimes WIP that you intend to rebase, and it hurts. Git porcelains should help you avoid to shoot yourself in the foot, hence I think that (especially to git newcomers), the current default _is_ dangerous. Though, OTOH, I believe that git push <remote> could keep the current behavior. I'm also okay with the fact that git push could be configurable in that regard. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
What's "dangerous" for newbies, often ends up being what doesn't correspond with their mental model. I think the current default behavior without any <refspec> specified corresponds well to the operation of many other git commands (and unix command) in similar circumstances: If you don't specify something to operate on, it essentially uses a wild card and operates on "every reasonable thing" (e.g., consider "git commit FILE" versus "git commit"). Even if the default were changed, it could very well end up causing many problems because it _didn't_ push as many heads as the user thought it would (I don't think I'm the only one that might expect the default action to be "push everything"). When I was a git newbie, I sometimes got into situations where I screwed something up because heads I thought had been pushed to another system actually hadn't been. To the extent that a command _is_ "dangerous", there's always a tradeoff between convenience and "danger". Some systems (e.g. those aimed at newbies) might have as a goal to do the absolute minimum with every command and always, always, err on the side of safety. I don't think git is that system. -Miles -- Yo mama's so fat when she gets on an elevator it HAS to go down. -
While much of this debate can be shortcircuited simply by making the behaviour configurable, I would like to take you up on the point that you raise here. If we're going to talk about what kind of system Git is then consider this: - it's inherently distributed and this design actively encourages users to treat their local repositories as sandboxes where things are tried out, perfected, and then pushed out into the public via one means or another - it's built from the ground up to be good at branching and merging; this, combined with my previous point, means that users are likely to have multiple heads and often some of them will be "works in progress" that aren't yet ready for publication So it's in that light I see accidentally pushing more than you thought you would as "dangerous"; when you make this mistake you're basically making stuff available that's not yet ready for consumption, and by its nature this mistake is basically irreversible: you can't really "unpush" what you pushed, you can only push out additional amendments which correct it. I don't know how much it has to do with mental models. I think in this case it's a bit simpler than that where you make the mistake once or twice and very quickly learn that "git push" means "push what's in my repo", not "push only what's on my current branch". It's a *very* easy lesson to learn if you get burnt and hardly requires any adjustments to ones "mental model". I personally would be in favour of changing the default because I tend to work on a particular branch at a time and then want to push *that* out -- generally I'm thinking about one general area or one task at a time, and that means one branch at a time; I almost never think along the lines of getting all my branches into shape at once and then pushing them out in a batch. I think this is more likely to be a common pattern, although obviously that remains speculation at this point. Changing the default w...
I completely second all that. I've been using Git for roughly 3 =20 months and have been burnt the same way. --=20 Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory
My vote is for changing it.
Both "push the current branch" and "push all branches" have their
uses, and both can be specified explicitly, so no problem there. The
problem arises when a user expects one default but get another. There
are two cases:
1. "push the current branch" is the default, but the user intended
to push all branches. She ends up pushing only a subset of what
she wanted, which is easily fixed once she notices what's
happened.
2. "push all branches" is the default, but the user intended to push
only the current branch. She ends up pushing a superset of what
she wanted, which is not easily fixed if she can't be sure that
no one else has pulled from the public repo before she notices
what's happened.
So it all comes down to case (2) mistakes being much harder to fix
than case (1) mistakes. Therefore, we should change the default, since
doing so makes it safer.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
-Hi, But that is not the default. Not at all. The default is to push the refs which the remote and the local side have _in common_. Maybe we should initialise the "remote.origin.push" variable to "completely-bogus-branchname" when you "git init --im-a-newbie"? Ciao, Dscho -
Yes, that's already been covered in this thread, probably in the first or second post, and (at least I hope) we've all read it and take it as given. Replace "push all branches" with "push all refs that both sides have in common", which is presumably what Karl meant, and the concerns are How is this comment supposed to help in any way? Please try to think about the image you're putting across; as an relatively active and prominent contributer in the Git community you are part of the "face" of the community. Cheers, Wincent -
I know, and that's what I meant by "all branches". Sorry for the I'd rather have a suboptimal default than different defaults depending on user settings. (See also Junio's comment on that elsewhere in this thread.) -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle -
Hi, This thread is getting painful. Lot's of "I want"s, but nobody to date came up with a solution that makes both oldtimers and newtimers happy. Ciao, Dscho -
I think I made a proposal that tries to reach some kind of consensus:
`git push`::
no arguments given just pushes the current branch you're on, into
origin, if a refspec matches.
`git push <remote>`::
works like now (aka pushes all branches that match a remote branch
in the given remote).
This way, you can have current "git push" using "git push origin", but
you also have a convenient way to push only the current branch into your
default remote repository without needing to spell out:
$ git push origin `git symbolic-ref HEAD`
--=20
=C2=B7O=C2=B7 Pierre Habouzit
=C2=B7=C2=B7O madcoder@debia=
n.org
OOO http://www.madism.orgHi, I use that sometimes, and I do not want only the current branch to be That would make things inconsistent, and inconsistent things are always I wonder how hard it would be to teach _everybody_ to specify _exactly_ what they want. Of course, we'd need an "--existing" option to git-push to trigger the behaviour that we have right now. Ciao, Dscho -
I could _definitely_ live with that. If the branch config doesn't say what to do when no arguments are given, then demand a specification on the command line. I'll shut up on this topic now, though, since I'm not exactly helping with the patch/opinion ratio. -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle -
Here is an interesting related pitfall where my expectations about
the behaviour of git push in relation with tracking branches were
wrong. I should have know better, but I somehow forgot the details.
I expected that the following would establish a two-way link, not
only a one way link:
git checkout --track -b mynext origin/next
sets up a tracking branch and "git pull" fetches and merges changes
from origin/next as expected.
I somehow expected that "git push" would push changes from mynext to
origin/next. But it doesn't. It would only do so if I had chosen
the same name for the local branch, that is
git checkout --track -b next origin/next
would have set up a two-way link -- but maybe only as long as I don't
have other push lines in my config file. I'm not sure about the last
point.
I do not find it very intuitive to mangle the push behaviour into the
naming of the local branch. I think it would be a good idea if the
two commands above would either both setup a pull/push relation
or both would setup a pull-only relation. If pull-only would be the
default another switch could be provided to establish a pull/push
relation, like
git checkout --track --push -b mynext origin/next
Comments?
Steffen-Interesting. To me that doesn't seem to be intuitive at all. I actually think it makes a lot of sense for the relationship to be "one way" in the absence of matching ref names. Basically, the distributed model works because you know that if you have the same commit hash in two repositories you're talking about the same thing. Same thing goes for branches; if you expect to be able to push back upstream then it's natural to expect that that should only work if you have the same ref name to identify the "what" that you're actually pushing to. Cheers, Wincent -
But how do multiple remotes fit into your model? Maybe my example
above was a bit to simple. How about this one:
git checkout --track --push -b masterA remoteA/master
git checkout --track --push -b masterB remoteB/master
I understand what it means because I devised my local naming model.
The model could look totally wrong to you, but it's in my repository.
You'd never see it. But if it fits my mental model, why should git
enforce its master-means-always-master-and-must-not-be-named-differently
model?
Steffen
-I think I'll leave it up to someone who knows a bit more than me to answer that one... It's not a use case I've ever sought out as I usually only work with one upstream remote. Sorry I don't have anything intelligent to add. Cheers, Wincent -
I am not convinced. I've seen many new people alias "rm" to "rm -i" for this (I'd say "false") reasoning to "default to safer", and end up training their fingers to say "y" without thinking. Also mistakes can cut both ways. Pushing out what you did not intend to is what you seem to be worried about more. But not pushing out enough and not noticing is an equally bad mistake. People also argue for "default per user". I am not really convinced on that point either. You, an expert, will get asked for help by somebody, walk up to his shell prompt, and try to help and teach him by showing you type, and then you suddenly notice the command does not work as you expect because he set the default differently (because he read that configuration option on some web parge). And we will be in such a cumbersome to diagnose situation _very_ often if we have per-user default on many things. -
I don't think that's a good analogy here, since no one is proposing It may be an equally bad mistake, but it's _not_ equally hard to fix. (And in my book, that means they aren't in fact equally bad.) You're right that some users will train their fingers to always type "git push --all" to the point where they will push everything by mistake even in cases where that's not what they wanted. But the same thing will happen with the current default for people who almost always push just a single branch, and train their fingers for that. I'm generally opposed to per-user settings for that reason. Users who insist can alias "pusha" to "push --all". -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle -
I don't think they're of the same order. If you mistakenly push out too little you can easily correct it by pushing again. But what do True, true. Cheers, Wincent -
Git commit is hardly a wildcard as it only operates on what you put in I beg to differ then. I believe that "git push" default behavior is wrong. I'm not really a newbie, and it often did not do what I meant. So it could also be that there isn't a sane default either. I just say the current one can lead to gross mistakes. I know that some porcelains are risky: if you rebase "under" a point that was published you are shooting yourself in the foot e.g.. But git-rebase _is_ a command that rewrites history. You're warned from the first second you use it. But git-push is supposedly only a transport command, not something that messes with remotes history behind your back. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
It could be more annoying for some, yet a life saver for others. So before changing the default obviously we would need to get a clear idea of whether or not the majority would approve of such a move. Such differences of opinion would be easily accommodated if the default behaviour were made configurable. That way everyone can have the behaviour they want. Cheers, Wincent PS. I'm the one who mentioned SVK, but I didn't offer it as a reason to justify the change (I agree, more than "weak" it's not really any reason at all); I just mentioned to indicate why it is that the current behaviour caught me off guard. -
Indeed. -Miles -- "Suppose we've chosen the wrong god. Every time we go to church we're just making him madder and madder." -- Homer Simpson -
Usually we hear people complain louder on the list. People who are happy with the existing behaviour tend to be quiet, and we should be really careful not to break things for silent majority. I try to stay fairly conservative, often more conservative than what I would like to be myself, for this exact reason. -
I'd certainly welcome this change for two reasons: 1. It makes the behaviour more conservative (that is, harder to do something destructive and irreversible) by using the more limited scope by default. If you make a mistake and see that you really meant to push all matching branches then you can just do the push again with that switch; compare that to the situation now where if you accidentally push all matching branches when you only wanted to push the current branch then there's no way for you to "unpush". 2. Mental baggage from working with SVK (where "push" means merge changes back to the branch the current branch previously branched from, and "pull" means merge changes into the current branch from the branch you previously branched from). At least for me and I suspect for many others the "current only" default in 1.6 or latter would be less "surprising" than the current behaviour can be. Cheers, Wincent -
I'm not sure that changing the fallback behaviour for unconfigured "remote.<name>.push" is sufficient. When "remote.<name>.push" is set I'd expect "git push" to choose only the 'right' remote.<name>.push lines, that is the lines that have the current branch as the local ref. "git push" would only push the current branch, which could be pushed to 0 or more branches on the remote side. If no "remote.<name>.push" contains the current branch as a local ref nothing would happen (maybe a warning?). If several "remote.<name>.push" have the current branch as the local ref the branch would be pushed to several remote branches. But other branches than the current branch would _never_ be pushed if no argument is given to 'git push'. Steffen -
That would break the existing setup so it would not fly as a default, although it could be added as an option. -
I would like this for another reason and maybe in slightly different way.
Basically I would have configured something along the lines:
[remote "origin"]
push =3D refs/heads/*:refs/heads/jahu/*
and would want to choose, via option, whether I want to push all the branch=
es
or just the current one, but in any case with the renaming specified.
The idea behind this is to have a shared repository, but not shared branche=
s.
Everybody would have a subdirectory in refs/heads where he could push
anything that the others should see and than somebody else (either designat=
ed
integrator, or just anybody different) would do a quick review and merge it
into master.
Now I could of course push out everything, but usually I'd want to push
exactly the current branch, renaming it by the rule given, whether it alrea=
dy
existed in origin or not. Than there can be eg. a post-receive hook notifyi=
ng
We can have an option and/or we can have some new parameter in .git/config.
Maybe:
push =3D refs/heads/*:refs/heads/jahu/*
would mean to push always (ie. everything under refs/heads) and eg.:
push =3D !refs/heads/*:refs/heads/jahu/*
would mean to push just current branch if it matches. Mixed setups would be
possible:
push =3D refs/heads/*:refs/heads/jahu/* !master:master !next:next
would mean push everything to jahu/ and if current is master, push it to
master, or if current is next, push it to next.
--=20
Jan 'Bulb' Hudec <bulb@ucw.cz>I had a similar scenario in mind. So a more general question is the following: Git well supports the clone from read-only and push to private repo scheme. In this case all repositories you're pushing to are by definition _your_ repositories. The only question left is, which subset of your branches are pushed. But there's no need for renaming during push. Now the question is, what is a sensible workflow on a shared repository? One option is to use some kind of private 'namespace' scheme. For example developers should push their topics to a branch prefixed with their name, or to a 'subdirectory' ref/heads/needsreview/*. This workflow may require to 'rename' branches during push. So how can this be supported by git? Supporting only renames that add a prefix, as suggested by Jan, may be reasonable restriction. Steffen -
Do you mean 'not now' or never, i.e. not in git 1.6? What does 'break the existing setup' means? Pushing all branches that are configured in "remote.<name>.push" could be done by "git push <name>". This would be in the line with the idea that "git push" should only operate on the current branch and operations involving other local refs should be explicitly stated. Steffen -
Hi, If it changes behaviour, and there might be people relying on the old behaviour, we have to deprecate the old behaviour first. With a nice warning so that people have a chance to adapt their setups. And then, People have scripts and aliases to help them go through the day. If one of those scripts or aliases stop working, that is called "break the existing setup". ;-) Ciao, Dscho -
I'm not really sure that it makes sense, as by default, git push won't create a new remote ref. So unless you have a branch that matches some remote ref, but that you never want to push, even when on it and typing git push... there is nothing that could happen by mistake. So if you don't want to push such a branch, ever, then you should IMHO not name it in a way that it matches a refspec in the first place, and be safe. So I do not believe we need that extra complexity. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
I could have a couple of local branches typically pushed to a couple of remote branches. "git push origin" would update all remote refs. But I may also be interested to push only the current branch I'm working on. I may also have some pending fixes on another branch that should not be pushed now. Currently I need to do "git push origin <current>:<someremote>". Let me put it as a question: How can I push changes from the current branch to all remote refs it is configured to push to via "remote.<name>.push" without pushing anything else at the same time? Steffen -
Sorry, but I do not get you. Are you talking about pushing your 'frotz' into more than one branches 'nitfol' and 'xyzzy' at the same remote 'origin' without having to say $ git push origin frotz:nitfol frotz:xyzzy ??? -
Yes. Doesn't sound like a very reasonable workflow. But you can do it with "remote.<name>.push". So I think "git push" should somehow deal with it in a sensible way. Steffen -
Sounds like a plan to me. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
I kind of agree. Without reading the git-push man page I would intuitively expect "git push" with no arguments to push only the Ah, nice alias! Thanks for sharing it. Cheers, Wincent -
Same thing here, got bitten the same way. --=20 Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory
| Pardo | Re: pthread_create() slow for many threads; also time to revisit 64b context switc... |
| Artem Bityutskiy | [RFC PATCH 06/26] UBIFS: add superblock and master node |
| Christian | 2.6.22-rc1 does not boot on VIA C3_2 cause of X86_CMPXCHG64 |
| Martin Schwidefsky | [GIT PULL] kernel message catalog patches |
git: | |
| David Kastrup | Empty directories... |
| Han-Wen Nienhuys | git branch performance problem? |
| Tim Ansell | Whats happening with git-notes? |
| Marco Costalba | [PATCH 11/11] Convert sha1_file.c to use decompress helpers |
| Mayuresh Kathe | Richard Stallman... |
| William Boshuck | Re: Longest Uptime? |
| Sean Hafeez | hostname.pppoe0 with AT&T/SBC debug? |
| new_guy | Re: Code signing in OpenBSD |
| Patrick Ohly | [RFC PATCH 00/13] hardware time stamping + igb example implementation |
| Johannes Berg | mac80211 truesize bugs |
| Denys | r8169 crash |
| Peter Zijlstra | Re: [tbench regression fixes]: digging out smelly deadmen. |
