{"thread":{"id":"11961","subject":"Minor annoyance with git push","startedAt":"2008-02-08T04:44:12Z","lastAt":"2008-02-22T00:11:25Z","messageCount":71,"participants":["Martin Langhoff","Sean","Steffen Prohaska","Junio C Hamano","Johannes Schindelin","Mike Hommey","Jeff King","Wincent Colaiuta","Steven Walter","Daniel Barkalow","Jay Soffian","Santi Béjar"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"67895","messageId":"46a038f90802072044u3329fd33w575c689cba2917ee@mail.gmail.com","threadId":"11961","inReplyTo":null,"subject":"Minor annoyance with git push","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-08T04:44:12Z","receivedAt":"2008-02-08T04:44:12Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"I have a minor UI issue with git pull. First, a bit of background: we\nrun a \"central team repo\" development model -- and we track on one\nrepo the \"main\" branches, and the client branches, where we do minor\ncustomisations and sometimes client-funded feature work that is later\ncherry-picked for the \"main\" branches. This is with a team of ~10\npeople, and lots of clients.\n\n(To clarify: some clients are in specialised private repositories.\nMost are happy and actually request that our work should be public.)\n\nAs we run a central repo, we all get *all* the branches when we do\nfetch. A bit noisy, but no major issue. It is also a great thing as we\nget asked to help in various branches, so I'll often hop on a client\nbranch that is mainly maintained by someone else, just to fix or\nenhance something on the authentication (which I specialise in). After\nthat, I don't have much to do with that client branch.\n\nThis means that beyond the branches I actively work on, I also have\nlocal tracking branches for remote heads that I am not updating. When\nI say git push, these stale local tracking branches are making a lot\nof noise in the output:\n\nTo git+ssh://git.catalyst.net.nz/var/git/moodle-r2.git\n ! [rejected]        mdl17-ceo -> mdl17-ceo (non-fast forward)\n ! [rejected]        mdl18-local -> mdl18-local (non-fast forward)\n ! [rejected]        mdl18-masseyedu-wimbatest ->\nmdl18-masseyedu-wimbatest (non-fast forward)\n ! [rejected]        mdl18-nmit -> mdl18-nmit (non-fast forward)\n ! [rejected]        mdl18-proxy -> mdl18-proxy (non-fast forward)\n ! [rejected]        mdl18-shared -> mdl18-shared (non-fast forward)\n ! [rejected]        mdl18-sqm -> mdl18-sqm (non-fast forward)\n ! [rejected]        mdl18-stcuthberts -> mdl18-stcuthberts (non-fast forward)\n ! [rejected]        mdl18-topnz -> mdl18-topnz (non-fast forward)\n ! [rejected]        mdl19-dbperf -> mdl19-dbperf (non-fast forward)\n ! [rejected]        mdl19-ucol -> mdl19-ucol (non-fast forward)\n ! [rejected]        mdl19-uow -> mdl19-uow (non-fast forward)\nerror: failed to push to 'git+ssh://git.catalyst.net.nz/var/git/moodle-r2.git'\n\nThe error messages (\"! rejected\", \"error: failed to push\") appear even\nif one or two branches did get pushed... I think they are a bit over\nthe top. None of these \"rejected\" branches have anything _new_, they\nare just stale. Nothing new to say. Can we just ignore them, and only\nsay \"ZOMG Failure! Rejected!!1!!\" if we fail to push *new* local\ncommits that aren't in the repo (leading to an assumption that if the\nuser said \"push\" he'd expect those new local commits to be pushed to\nthe server)?\n\n[ Personally, it doesn't bother me too much. But I can see some\nnewcomers to my team, and their eyes twitch when they see all the\nexclamation marks. I've learned to look for the branch I care about\nbeing pushed in the output, but it's particularly not user friendly as\nit stands. ]\n\ncheers,\n\n\n\nm\n"},{"id":"67896","messageId":"46a038f90802072050s46ffe305mcffffa068511e3b8@mail.gmail.com","threadId":"11961","inReplyTo":"46a038f90802072044u3329fd33w575c689cba2917ee@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-08T04:50:36Z","receivedAt":"2008-02-08T04:50:36Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Feb 8, 2008 5:44 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:\n>  None of these \"rejected\" branches have anything _new_, they\n> are just stale. Nothing new to say.\n\nAnd I guess the natural follow up question is: would it make sense to\ntell git pull to do a \"merge\" for not-checked-out branches where we\ncan safely tell that the resulting \"merge\" will actually be a\nfast-forward?\n\nWould that be unsafe in any way?\n\nBecause when I \"git checkout bla-stale-branch\" to help a fellow\ndeveloper again, I have to remember to \"git merge\norigin/bla-stale-branch\" to get a much needed fast-forward before\nstarting to work.\n\n[ Or we could be more proactive at deleting unused local heads. But\nthat's a bit of silly maintenance just to keep things tidy, that git\ncould keep tidy ;-) ... ]\n\ncheers,\n\n\nm\n"},{"id":"67898","messageId":"BAYC1-PASMTP0989BAD99482FD877540CBAE2F0@CEZ.ICE","threadId":"11961","inReplyTo":"46a038f90802072044u3329fd33w575c689cba2917ee@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2008-02-08T05:38:36Z","receivedAt":"2008-02-08T05:38:36Z","isPatch":false,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Fri, 8 Feb 2008 17:44:12 +1300\n\"Martin Langhoff\" <martin.langhoff@gmail.com> wrote:\n\n> This means that beyond the branches I actively work on, I also have\n> local tracking branches for remote heads that I am not updating. When\n> I say git push, these stale local tracking branches are making a lot\n> of noise in the output:\n\nThere may be other workflows where the noise in the output is appropriate.\nWhat about using \"git push origin HEAD\" (or an alias for it) to push only\nthe branch you have checked out and avoid noise for other branches?\n\nSean\n"},{"id":"67900","messageId":"0AF54F9D-9B5C-41F5-A65C-B8BB50DC0D80@zib.de","threadId":"11961","inReplyTo":"BAYC1-PASMTP0989BAD99482FD877540CBAE2F0@CEZ.ICE","subject":"Re: Minor annoyance with git push","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2008-02-08T06:29:32Z","receivedAt":"2008-02-08T06:29:32Z","isPatch":false,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Feb 8, 2008, at 6:38 AM, Sean wrote:\n\n> On Fri, 8 Feb 2008 17:44:12 +1300\n> \"Martin Langhoff\" <martin.langhoff@gmail.com> wrote:\n>\n>> This means that beyond the branches I actively work on, I also have\n>> local tracking branches for remote heads that I am not updating. When\n>> I say git push, these stale local tracking branches are making a lot\n>> of noise in the output:\n>\n> There may be other workflows where the noise in the output is  \n> appropriate.\n> What about using \"git push origin HEAD\" (or an alias for it) to  \n> push only\n> the branch you have checked out and avoid noise for other branches?\n\n\nThis is what I often do and I also tell my users from\nthe very beginning to *avoid* a naked \"git push\".\nInstead, they always should say exactly what they mean,\nlike \"git push origin topic\", and they can use\n\"git push origin HEAD\" as a short-hand.  Besides, they\nshould also run with \"--dry-run\" first to verify what\nthey do.\n\nWe had lengthy discussions about the issue Martin describes.  My\npersonal conclusion was that people on the list tend to regard\nthe current behaviour of \"git push\" as a very stable feature.  So\nyou should come up with convincing arguments for changes and\nyou also should ensure that the current behaviour does not break.\nI decided to focus on different things and leave \"git push\" as is.\n\nHere are some pointers to the discussions:\n\nhttp://marc.info/?l=git&m=119384331712996&w=2\n\nhttp://marc.info/?l=git&m=119400354601328&w=2\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/65632/focus=65747\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/61955/focus=65493\n\n\tSteffen\n"},{"id":"67908","messageId":"7vwspfkhxm.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"46a038f90802072050s46ffe305mcffffa068511e3b8@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-08T07:48:05Z","receivedAt":"2008-02-08T07:48:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Martin Langhoff\" <martin.langhoff@gmail.com> writes:\n\n> On Feb 8, 2008 5:44 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:\n>>  None of these \"rejected\" branches have anything _new_, they\n>> are just stale. Nothing new to say.\n>\n> And I guess the natural follow up question is: would it make sense to\n> tell git pull to do a \"merge\" for not-checked-out branches where we\n> can safely tell that the resulting \"merge\" will actually be a\n> fast-forward?\n>\n> Would that be unsafe in any way?\n\nNot \"unsafe\" in the sense that you would not be losing commit\nobjects, but I'd feel uneasy about that.  The fact that the\nbranch tip was pointing at an older commit gets lost, and in\nyour workflow that information is useless, but that does not\nnecessarily mean it is useless for everybody.\n\n> Because when I \"git checkout bla-stale-branch\" to help a fellow\n> developer again, I have to remember to \"git merge\n> origin/bla-stale-branch\" to get a much needed fast-forward before\n> starting to work.\n\nPerhaps it might make sense to have a checkout hook that notices\nthe branch that is being checked out is meant to build on top of\na corresponding remote tracking branch, and performs the\nnecessary fast-forward when that is the case.\n\n> [ Or we could be more proactive at deleting unused local heads. But\n> that's a bit of silly maintenance just to keep things tidy, that git\n> could keep tidy ;-) ... ]\n\nWell, git couldn't, unless you tell it \"I've pushed out my work,\nand I am done with helping with this client branch for now\", and\nthe way for you to do so is \"git branch -d\".\n\nPerhaps \"git branch -d\" should be taught to check if the tip of\nthe deleted branch is part of the corresponding remote tracking\nbranch, when \"one local branch to track one remote branch\" model\nis used.  Its safety to forbid deleting the branch unless it is\nan ancestor of the \"current\" branch would not make sense in such\na workflow.\n"},{"id":"67934","messageId":"alpine.LSU.1.00.0802081142060.11591@racer.site","threadId":"11961","inReplyTo":"46a038f90802072044u3329fd33w575c689cba2917ee@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-08T11:50:32Z","receivedAt":"2008-02-08T11:50:32Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 Feb 2008, Martin Langhoff wrote:\n\n> To git+ssh://git.catalyst.net.nz/var/git/moodle-r2.git\n>  ! [rejected]        mdl17-ceo -> mdl17-ceo (non-fast forward)\n>  ! [rejected]        mdl18-local -> mdl18-local (non-fast forward)\n>  ! [rejected]        mdl18-masseyedu-wimbatest ->\n> mdl18-masseyedu-wimbatest (non-fast forward)\n>  ! [rejected]        mdl18-nmit -> mdl18-nmit (non-fast forward)\n>  ! [rejected]        mdl18-proxy -> mdl18-proxy (non-fast forward)\n>  ! [rejected]        mdl18-shared -> mdl18-shared (non-fast forward)\n>  ! [rejected]        mdl18-sqm -> mdl18-sqm (non-fast forward)\n>  ! [rejected]        mdl18-stcuthberts -> mdl18-stcuthberts (non-fast forward)\n>  ! [rejected]        mdl18-topnz -> mdl18-topnz (non-fast forward)\n>  ! [rejected]        mdl19-dbperf -> mdl19-dbperf (non-fast forward)\n>  ! [rejected]        mdl19-ucol -> mdl19-ucol (non-fast forward)\n>  ! [rejected]        mdl19-uow -> mdl19-uow (non-fast forward)\n> error: failed to push to 'git+ssh://git.catalyst.net.nz/var/git/moodle-r2.git'\n> \n> The error messages (\"! rejected\", \"error: failed to push\") appear even\n> if one or two branches did get pushed... I think they are a bit over\n> the top. None of these \"rejected\" branches have anything _new_, they\n> are just stale.\n\nSo you're saying that the local sides' refs are ancestors of the remote \nsides' refs?\n\nThe problem is that the local side cannot tell, and we try to avoid \nputting load on the server, because in many cases, there will be one \ncentral server and many clients.\n\nSo I think this is not technically feasible.  Or do you have another idea \nhow to find out that the \"[rejected]\" ref is a stale ref (i.e. an ancestor \nof the remote side) as opposed to properly rejected?\n\nAnother way to \"solve\" this issue, of course, is to use the remote layout.  \nI did the switchover myself some time ago; it was hard at first, since I \nwas so used to just check out the branches I just fetched.  But in the \nlong run the distinction between local and tracking branches made life \nmuch easier for me.\n\nRelated is this idea that I did not really follow up: often, you want to \nwork on a branch which you are tracking already, but there is no local \nbranch.  And most often, you just want to create a local branch of the \nsame name.  So maybe we should just introduce a new flag, like\n\n\t$ git checkout -c origin/next\n\nwhich would create (or fast-forward) the local branch \"next\" to what's in \norigin/next.  The long option would read --create-local.\n\nIn the same vein, maybe \"git branch -d next\" should be taught to look at \nthe remote branches of name \"<nick>/next\", too, when checking if that ref \nis an ancestor of HEAD?\n\nCiao,\nDscho\n"},{"id":"67935","messageId":"alpine.LSU.1.00.0802081151170.11591@racer.site","threadId":"11961","inReplyTo":"46a038f90802072050s46ffe305mcffffa068511e3b8@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-08T11:52:44Z","receivedAt":"2008-02-08T11:52:44Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 Feb 2008, Martin Langhoff wrote:\n\n> On Feb 8, 2008 5:44 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:\n> >  None of these \"rejected\" branches have anything _new_, they are just \n> > stale. Nothing new to say.\n> \n> And I guess the natural follow up question is: would it make sense to \n> tell git pull to do a \"merge\" for not-checked-out branches where we can \n> safely tell that the resulting \"merge\" will actually be a fast-forward?\n\nThat question comes up pretty often, I think.  But you need a working \ndirectory to resolve conflicts for merges.  You only have one, though.\n\nSo no, I think it is saner to have tracking branches (which are updated \nanyway), and local branches.  And once you're done with a branch, you \nsimply push it, and then delete it (you will still have the result in the \ntracking branch).\n\nCiao,\nDscho\n"},{"id":"68020","messageId":"46a038f90802081423v13a19a65oe842b94ba7f85528@mail.gmail.com","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802081151170.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-08T22:23:30Z","receivedAt":"2008-02-08T22:23:30Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Feb 9, 2008 12:52 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> That question comes up pretty often, I think.  But you need a working\n> directory to resolve conflicts for merges.  You only have one, though.\n\nOnce all the remote refs are fetched, it is trivial to determine that\nit is just a fast-forward, therefore _no_ merge and no chance for\nconflicts...\n\ncheers,\n\n\nm\n"},{"id":"68021","messageId":"20080208222722.GA24474@glandium.org","threadId":"11961","inReplyTo":"46a038f90802081423v13a19a65oe842b94ba7f85528@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2008-02-08T22:27:22Z","receivedAt":"2008-02-08T22:27:22Z","isPatch":false,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"On Sat, Feb 09, 2008 at 11:23:30AM +1300, Martin Langhoff wrote:\n> On Feb 9, 2008 12:52 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > That question comes up pretty often, I think.  But you need a working\n> > directory to resolve conflicts for merges.  You only have one, though.\n> \n> Once all the remote refs are fetched, it is trivial to determine that\n> it is just a fast-forward, therefore _no_ merge and no chance for\n> conflicts...\n\nEven with merges, it could be helpful to have a tool that would\nautomagically stash, checkout the appropriate branch, merge (and deal\nwith conflicts if necessary), and so on.\n\nMike\n"},{"id":"68022","messageId":"46a038f90802081427k6ee94cfagbc02533538e75b49@mail.gmail.com","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802081142060.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-08T22:27:51Z","receivedAt":"2008-02-08T22:27:51Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Feb 9, 2008 12:50 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> So you're saying that the local sides' refs are ancestors of the remote\n> sides' refs?\n\nExactly. And we could show a nicer message - rejected is too strong a word ;-)\n\n> The problem is that the local side cannot tell\n\nThe local side has the remote refs if the client has fetched recently,\nso it might be able to tell in some cases. Not with authority (things\nmay have changed on the server side...) but the client might be able\nto say something less alarming.\n\n> Another way to \"solve\" this issue, of course, is to use the remote layout.\n> I did the switchover myself some time ago; it was hard at first, since I\n> was so used to just check out the branches I just fetched.  But in the\n> long run the distinction between local and tracking branches made life\n> much easier for me.\n\nWhat do you mean with \"the remote layout\"? I am using\n\"remotes\"+tracking branches as far as I can tell...\n\ncheers,\n\n\nm\n"},{"id":"68026","messageId":"alpine.LSU.1.00.0802082256290.11591@racer.site","threadId":"11961","inReplyTo":"46a038f90802081427k6ee94cfagbc02533538e75b49@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-08T22:57:36Z","receivedAt":"2008-02-08T22:57:36Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Feb 2008, Martin Langhoff wrote:\n\n> On Feb 9, 2008 12:50 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> \n> > The problem is that the local side cannot tell\n> \n> The local side has the remote refs if the client has fetched recently, \n> so it might be able to tell in some cases. Not with authority (things \n> may have changed on the server side...) but the client might be able to \n> say something less alarming.\n\nBut if it was not fetched recently?  I think that what you suggest is too \ntricky (IOW too prone to break).\n\n> > Another way to \"solve\" this issue, of course, is to use the remote \n> > layout. I did the switchover myself some time ago; it was hard at \n> > first, since I was so used to just check out the branches I just \n> > fetched.  But in the long run the distinction between local and \n> > tracking branches made life much easier for me.\n> \n> What do you mean with \"the remote layout\"? I am using \"remotes\"+tracking \n> branches as far as I can tell...\n\nI mean keeping most branches purely as tracking branches.  Whenever you \nare done with one branch, you delete the local branch.\n\nCiao,\nDscho\n"},{"id":"68042","messageId":"20080209024636.GE2572@coredump.intra.peff.net","threadId":"11961","inReplyTo":"46a038f90802081427k6ee94cfagbc02533538e75b49@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-09T02:46:36Z","receivedAt":"2008-02-09T02:46:36Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 09, 2008 at 11:27:51AM +1300, Martin Langhoff wrote:\n\n> Exactly. And we could show a nicer message - rejected is too strong a\n> word ;-)\n\nLike\n\ndiff --git a/builtin-send-pack.c b/builtin-send-pack.c\nindex 454ad8f..3979918 100644\n--- a/builtin-send-pack.c\n+++ b/builtin-send-pack.c\n@@ -315,7 +315,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count)\n \t\t\t\tref->peer_ref, NULL);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NONFASTFORWARD:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n+\t\tprint_ref_status('!', \"[kindly refused]\", ref, ref->peer_ref,\n \t\t\t\t\"non-fast forward\");\n \t\tbreak;\n \tcase REF_STATUS_REMOTE_REJECT:\n\n?\n\n> The local side has the remote refs if the client has fetched recently,\n> so it might be able to tell in some cases. Not with authority (things\n> may have changed on the server side...) but the client might be able\n> to say something less alarming.\n\nThis is actually not that hard to do in the case that we can. Patch will\nfollow in a second, though I am not sure it is a good idea (because it\nsilently ignores pushing rewinds).\n\n> > Another way to \"solve\" this issue, of course, is to use the remote layout.\n> > I did the switchover myself some time ago; it was hard at first, since I\n> > was so used to just check out the branches I just fetched.  But in the\n> > long run the distinction between local and tracking branches made life\n> > much easier for me.\n> \n> What do you mean with \"the remote layout\"? I am using\n> \"remotes\"+tracking branches as far as I can tell...\n\nI think he means something like \"if I have 'next' and 'origin/next',\nthen I should check whether 'next' is a subset of 'origin/next'\" and\njust say \"nothing to send.\" But that suffers from the same \"silently\nignoring rewinds\" as above. You could ignore the push if you have\nnext exactly equal to origin/next, but that implies that you haven't done\nany fetching (which is unlikely in the scenario you described).\n\n-Peff\n"},{"id":"68043","messageId":"20080209025431.GF2572@coredump.intra.peff.net","threadId":"11961","inReplyTo":"20080209024636.GE2572@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-09T02:54:31Z","receivedAt":"2008-02-09T02:54:31Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 08, 2008 at 09:46:36PM -0500, Jeff King wrote:\n\n> > The local side has the remote refs if the client has fetched recently,\n> > so it might be able to tell in some cases. Not with authority (things\n> > may have changed on the server side...) but the client might be able\n> > to say something less alarming.\n> \n> This is actually not that hard to do in the case that we can. Patch will\n> follow in a second, though I am not sure it is a good idea (because it\n> silently ignores pushing rewinds).\n\nAnd here it is. Again, I don't think this is the right default behavior.\nI'm not even sure it is a good idea as configurable behavior. But it's\nhere for comment and for playing with, nonetheless.\n\n-- >8 --\nsend-pack: treat strict rewinds specially\n\nIf you try to push an out-of-date version of a branch, it will generally\nbe rejected as a non-fastforward. This can clutter up the status output\nof git-push if you have many such branches.\n\nInstead, let's check explicitly whether what we are pushing is a strict\nsubset of what the remote already has. We treat this as a non-error, and\ndon't even print any status unless \"verbose\" is given. If the push is\n\"forced\", then we will push as usual.\n\nNote that we cannot always perform this check accurately; it relies on\nus having the commit object that the remote claims to have. In the case\nthat we don't, we treat it like an ordinary non-fastforward and reject.\n\n---\ndiff --git a/cache.h b/cache.h\nindex 920e731..78fee0b 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -596,6 +596,7 @@ struct ref {\n \t\tREF_STATUS_UPTODATE,\n \t\tREF_STATUS_REMOTE_REJECT,\n \t\tREF_STATUS_EXPECTING_REPORT,\n+\t\tREF_STATUS_REJECT_REWIND,\n \t} status;\n \tchar *remote_status;\n \tstruct ref *peer_ref; /* when renaming */\ndiff --git a/builtin-send-pack.c b/builtin-send-pack.c\nindex 454ad8f..9f82b83 100644\n--- a/builtin-send-pack.c\n+++ b/builtin-send-pack.c\n@@ -315,6 +315,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count)\n \t\t\t\tref->peer_ref, NULL);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NONFASTFORWARD:\n+\tcase REF_STATUS_REJECT_REWIND:\n \t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n \t\t\t\t\"non-fast forward\");\n \t\tbreak;\n@@ -343,7 +344,8 @@ static void print_push_status(const char *dest, struct ref *refs)\n \n \tif (args.verbose) {\n \t\tfor (ref = refs; ref; ref = ref->next)\n-\t\t\tif (ref->status == REF_STATUS_UPTODATE)\n+\t\t\tif (ref->status == REF_STATUS_UPTODATE ||\n+\t\t\t    ref->status == REF_STATUS_REJECT_REWIND)\n \t\t\t\tn += print_one_push_status(ref, dest, n);\n \t}\n \n@@ -354,7 +356,8 @@ static void print_push_status(const char *dest, struct ref *refs)\n \tfor (ref = refs; ref; ref = ref->next) {\n \t\tif (ref->status != REF_STATUS_NONE &&\n \t\t    ref->status != REF_STATUS_UPTODATE &&\n-\t\t    ref->status != REF_STATUS_OK)\n+\t\t    ref->status != REF_STATUS_OK &&\n+\t\t    ref->status != REF_STATUS_REJECT_REWIND)\n \t\t\tn += print_one_push_status(ref, dest, n);\n \t}\n }\n@@ -365,6 +368,7 @@ static int refs_pushed(struct ref *ref)\n \t\tswitch(ref->status) {\n \t\tcase REF_STATUS_NONE:\n \t\tcase REF_STATUS_UPTODATE:\n+\t\tcase REF_STATUS_REJECT_REWIND:\n \t\t\tbreak;\n \t\tdefault:\n \t\t\treturn 1;\n@@ -463,8 +467,12 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest\n \t\t    (!has_sha1_file(ref->old_sha1)\n \t\t      || !ref_newer(new_sha1, ref->old_sha1));\n \n+\n \t\tif (ref->nonfastforward && !ref->force && !args.force_update) {\n-\t\t\tref->status = REF_STATUS_REJECT_NONFASTFORWARD;\n+\t\t\tif (ref_newer(ref->old_sha1, new_sha1))\n+\t\t\t\tref->status = REF_STATUS_REJECT_REWIND;\n+\t\t\telse\n+\t\t\t\tref->status = REF_STATUS_REJECT_NONFASTFORWARD;\n \t\t\tcontinue;\n \t\t}\n \n@@ -522,6 +530,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest\n \t\tcase REF_STATUS_NONE:\n \t\tcase REF_STATUS_UPTODATE:\n \t\tcase REF_STATUS_OK:\n+\t\tcase REF_STATUS_REJECT_REWIND:\n \t\t\tbreak;\n \t\tdefault:\n \t\t\treturn -1;\n"},{"id":"68044","messageId":"20080209030046.GA10470@coredump.intra.peff.net","threadId":"11961","inReplyTo":"46a038f90802072044u3329fd33w575c689cba2917ee@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-09T03:00:46Z","receivedAt":"2008-02-09T03:00:46Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 08, 2008 at 05:44:12PM +1300, Martin Langhoff wrote:\n\n> This means that beyond the branches I actively work on, I also have\n> local tracking branches for remote heads that I am not updating. When\n> I say git push, these stale local tracking branches are making a lot\n> of noise in the output:\n> \n> To git+ssh://git.catalyst.net.nz/var/git/moodle-r2.git\n>  ! [rejected]        mdl17-ceo -> mdl17-ceo (non-fast forward)\n>  ! [rejected]        mdl18-local -> mdl18-local (non-fast forward)\n>  ! [rejected]        mdl18-masseyedu-wimbatest ->\n> mdl18-masseyedu-wimbatest (non-fast forward)\n>  ! [rejected]        mdl18-nmit -> mdl18-nmit (non-fast forward)\n>  ! [rejected]        mdl18-proxy -> mdl18-proxy (non-fast forward)\n>  ! [rejected]        mdl18-shared -> mdl18-shared (non-fast forward)\n>  ! [rejected]        mdl18-sqm -> mdl18-sqm (non-fast forward)\n>  ! [rejected]        mdl18-stcuthberts -> mdl18-stcuthberts (non-fast forward)\n>  ! [rejected]        mdl18-topnz -> mdl18-topnz (non-fast forward)\n>  ! [rejected]        mdl19-dbperf -> mdl19-dbperf (non-fast forward)\n>  ! [rejected]        mdl19-ucol -> mdl19-ucol (non-fast forward)\n>  ! [rejected]        mdl19-uow -> mdl19-uow (non-fast forward)\n> error: failed to push to 'git+ssh://git.catalyst.net.nz/var/git/moodle-r2.git'\n\nThinking about this more, this situation is more than a minor annoyance:\nit is actually somewhat dangerous. If you ever wanted to push _one_\nnon-ff case (say, for your current branch) and you were to use \"git push\n-f\", you would rewind history for random branches, and sorting the mess\nout at the remote could be awful (especially if it is a bare repo\nwithout reflogs).\n\nI really think that Steffen's \"default to pushing only the current\nbranch\" approach fits much better with the model described in your\nworkflow, and is generally a safer default. IIRC, the main objection was\nthat old-timers like the current push behavior better. Steffen, was\nthere objection to a \"push.onlyHEAD\" config option?\n\n-Peff\n"},{"id":"68045","messageId":"7vtzkihkx5.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"20080209030046.GA10470@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-09T03:24:06Z","receivedAt":"2008-02-09T03:24:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Thinking about this more, this situation is more than a minor annoyance:\n> it is actually somewhat dangerous. If you ever wanted to push _one_\n> non-ff case (say, for your current branch) and you were to use \"git push\n> -f\", you would rewind history for random branches, and sorting the mess\n> out at the remote could be awful (especially if it is a bare repo\n> without reflogs).\n\nYeah, -f using \"matching refs\" is dangerous, but on the other\nhand, that would be how you correct that mistake in one shot,\nafter you fixed the mistake locally.\n\nIs there anything wrong with \"git push $there $branch_name\"?  I\nthought we discussed this last time and there was even a patch\nthat does \"git push $there HEAD\" to push out the current branch,\nwhich I am fairly sure that I accepted (but I do not remember,\nas I do not use such a shorthand. When I want to push a single\nbranch, I _want_ to be explicit, to make sure I push out the\nright thing).\n\nSo after doing a fix on a single branch, you would:\n\n\t$ git push origin HEAD\n\nand you are done.  No need to spell out the long branch name you\nare currently on.\n\nI do not know if this was part of the last round of patches, but\nI suspect it is not a problem to allow\n\n\t$ git push HEAD\n\nif it is unambiguous.  That is, \"HEAD?  Do we have such a remote\nnickname?  No.  Then can we default to 'origin' and use it as\nthe ref to push?  Yeah, we can, so the user meant 'git push\norigin HEAD'\".\n"},{"id":"68046","messageId":"20080209035520.GA10709@coredump.intra.peff.net","threadId":"11961","inReplyTo":"7vtzkihkx5.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-09T03:55:20Z","receivedAt":"2008-02-09T03:55:20Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 08, 2008 at 07:24:06PM -0800, Junio C Hamano wrote:\n\n> Yeah, -f using \"matching refs\" is dangerous, but on the other\n> hand, that would be how you correct that mistake in one shot,\n> after you fixed the mistake locally.\n\nNot necessarily; you might not even have the refs that you just rewound.\n\n> Is there anything wrong with \"git push $there $branch_name\"?  I\n\nI think only that:\n\n  - it's more typing, so if there is a class of users who want to use\n    \"git push origin HEAD\" as their workflow, it might make sense to\n    support them with a config option\n\n  - I have seen less experienced users expecting \"git push\" to do a\n    single branch (i.e., users whose workflow is \"git pull; hack hack\n    hack; git push\").\n    With one branch it is not a problem, but as soon as you introduce\n    them to other branches, then the push behavior is yet another thing\n    that you have to explain. And I know \"clueless users\" is not a good\n    reason to change defaults if it makes clueful users less happy, but\n    it might be reason for a config option.\n\n> thought we discussed this last time and there was even a patch\n> that does \"git push $there HEAD\" to push out the current branch,\n\nAh, I forgot about that. Yes, that does work in 1.5.4.\n\n> I do not know if this was part of the last round of patches, but\n> I suspect it is not a problem to allow\n> \n> \t$ git push HEAD\n> \n> if it is unambiguous.  That is, \"HEAD?  Do we have such a remote\n> nickname?  No.  Then can we default to 'origin' and use it as\n> the ref to push?  Yeah, we can, so the user meant 'git push\n> origin HEAD'\".\n\nI have often wanted that, since I typically only _ever_ push to an\norigin, but the DWIM made me paranoid that it could be unsafe. If you\nhad a remote and a branch name that were similar, then a typo could end\nup pushing to the wrong place.\n\n-Peff\n"},{"id":"68065","messageId":"6B804F0D-9C3B-46F3-B922-7A5CBEF55522@zib.de","threadId":"11961","inReplyTo":"20080209030046.GA10470@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2008-02-09T10:53:22Z","receivedAt":"2008-02-09T10:53:22Z","isPatch":false,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Feb 9, 2008, at 4:00 AM, Jeff King wrote:\n\n>\n> I really think that Steffen's \"default to pushing only the current\n> branch\" approach fits much better with the model described in your\n> workflow, and is generally a safer default. IIRC, the main  \n> objection was\n> that old-timers like the current push behavior better. Steffen, was\n> there objection to a \"push.onlyHEAD\" config option?\n\nThere might have been an argument like: We should have a single\ndefault because otherwise the behaviour of git depends on the\nlocal configuration of the user.  This may cause even more\nconfusion than it tries to solve, because now you always need\nto start first talking about the local configuration of the\nusers before you can start explaining how to actually solve the\nproblem.\n\nPersonally, I decided it is safer to teach users to explicitly\ntype what they mean.  I'd probably not use the push.onlyHEAD\nconfig option.\n\nI also proposed that the default could do nothing if no explicit\npush lines are in the configuration file.  Users would be forced\nto explicitly type what the want: Either they can say \"--matching\"\nor they can say \"--current\".  This is similar to the new\n\"git clean\" default.  But I remember there *was* objection against\nthis because everyone would be forced to type more and different\nthan \"git clean\" the default of \"git push\" is considered \"safe\",\nso there's no need to protect the user from \"git push\".\n\nJunio proposed various possible changes to the configuration\nvariables that could resolve the issues.  I do not remember the\ndetails.\n\n\tSteffen\n"},{"id":"68068","messageId":"3AA71024-080B-4252-8416-82AE38A4498E@zib.de","threadId":"11961","inReplyTo":"7vwspfkhxm.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2008-02-09T11:22:33Z","receivedAt":"2008-02-09T11:22:33Z","isPatch":false,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Feb 8, 2008, at 8:48 AM, Junio C Hamano wrote:\n\n> \"Martin Langhoff\" <martin.langhoff@gmail.com> writes:\n>\n>> Because when I \"git checkout bla-stale-branch\" to help a fellow\n>> developer again, I have to remember to \"git merge\n>> origin/bla-stale-branch\" to get a much needed fast-forward before\n>> starting to work.\n>\n> Perhaps it might make sense to have a checkout hook that notices\n> the branch that is being checked out is meant to build on top of\n> a corresponding remote tracking branch, and performs the\n> necessary fast-forward when that is the case.\n\nOr just print a warning that there are new commits on the\ntracked branch and leave the decision how to proceed to\nthe user?\n\n\tSteffen\n"},{"id":"68067","messageId":"0456DF67-E0CB-4048-BB19-397D0C559F23@zib.de","threadId":"11961","inReplyTo":"20080209024636.GE2572@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2008-02-09T11:22:37Z","receivedAt":"2008-02-09T11:22:37Z","isPatch":false,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Feb 9, 2008, at 3:46 AM, Jeff King wrote:\n\n>>> Another way to \"solve\" this issue, of course, is to use the  \n>>> remote layout.\n>>> I did the switchover myself some time ago; it was hard at first,  \n>>> since I\n>>> was so used to just check out the branches I just fetched.  But  \n>>> in the\n>>> long run the distinction between local and tracking branches made  \n>>> life\n>>> much easier for me.\n>>\n>> What do you mean with \"the remote layout\"? I am using\n>> \"remotes\"+tracking branches as far as I can tell...\n>\n> I think he means something like \"if I have 'next' and 'origin/next',\n> then I should check whether 'next' is a subset of 'origin/next'\" and\n> just say \"nothing to send.\" But that suffers from the same \"silently\n> ignoring rewinds\" as above. You could ignore the push if you have\n> next exactly equal to origin/next, but that implies that you  \n> haven't done\n> any fetching (which is unlikely in the scenario you described).\n\n\nA similar proposal was discussed last October/November and we\nalready had patches.  We decided against it.  The reason is\nthat the post-condition of \"git push\" is that all heads that\nare considered by the push shall be identical locally and\nat the remote.  If \"git push\" does not achieve this it should\nreport the branches for which the post-condition is not met.\n\nI think Dscho means: do not duplicate remote branches as local\nbranches.  Keep the number of local branches as low as possible.\nOnly if you want to work on a remote branch, create a local\nbranch, commit you work, push, and *delete* the local branch.\n\nHowever, I often use local branches as a reminder which remote\nbranches I am actively monitoring.  If I start to work on them\nI first review what's new with \"gitk origin/topic --not topic\"\nand then do the fast forward \"git push . origin/topic:topic\"\nbefore I actually start working \"git checkout topic\". For\nthese branches, Dschos proposal does not work for me.\n\n\tSteffen\n"},{"id":"68071","messageId":"46a038f90802090350rc4780d1ted60c03b9abf1fc0@mail.gmail.com","threadId":"11961","inReplyTo":"7vtzkihkx5.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-09T11:50:20Z","receivedAt":"2008-02-09T11:50:20Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Feb 9, 2008 4:24 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Is there anything wrong with \"git push $there $branch_name\"?\n\nThis works, but is rather verbose to type all the time.\n\n>         $ git push origin HEAD\n>\n> and you are done.  No need to spell out the long branch name you\n> are currently on.\n\nDidn't know this was meant to work. I'll give it a go.\n\n> I do not know if this was part of the last round of patches, but\n> I suspect it is not a problem to allow\n>\n>         $ git push HEAD\n>\n> if it is unambiguous.  That is, \"HEAD?  Do we have such a remote\n> nickname?  No.  Then can we default to 'origin' and use it as\n> the ref to push?  Yeah, we can, so the user meant 'git push\n> origin HEAD'\".\n\nIf I can say git push HEAD it will be nice.\n\nStill, the big fat ![rejected] do seem over the top when I know it\nreally means \"stale\".\n\nAnd I don't completely follow how bad the impact of\nauto-fast-forwarding local tracking branches on a merge. If it's a\nfast-forward, my \"local state\" wasn't that exciting to begin with ;-)\nand revlogs can potentially rescue my olden state (but what's the use\ncase for the local state being interesting, anyway?). Yes - user state\nis important, but something that resolves to a fast-forward means that\nthe user state, whatever it is, is in sync with the repo.\n\nAs per the subject, these are minor annoyances. The whole\nremotes+local heads setup works like a charm ;-)\n\ncheers,\n\n\n\nm\n"},{"id":"68073","messageId":"alpine.LSU.1.00.0802091302550.11591@racer.site","threadId":"11961","inReplyTo":"20080209025431.GF2572@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-09T13:04:10Z","receivedAt":"2008-02-09T13:04:10Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 Feb 2008, Jeff King wrote:\n\n> On Fri, Feb 08, 2008 at 09:46:36PM -0500, Jeff King wrote:\n> \n> > > The local side has the remote refs if the client has fetched recently,\n> > > so it might be able to tell in some cases. Not with authority (things\n> > > may have changed on the server side...) but the client might be able\n> > > to say something less alarming.\n> > \n> > This is actually not that hard to do in the case that we can. Patch will\n> > follow in a second, though I am not sure it is a good idea (because it\n> > silently ignores pushing rewinds).\n> \n> And here it is. Again, I don't think this is the right default behavior.\n> I'm not even sure it is a good idea as configurable behavior. But it's\n> here for comment and for playing with, nonetheless.\n\nI was already trying to make a patch on top of yours which says \"[stale]\" \ninstead of \"[rejected]\" for those cases, but then I realised that 2 tests \nin t5400 fail.\n\n> @@ -463,8 +467,12 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest\n>  \t\t    (!has_sha1_file(ref->old_sha1)\n>  \t\t      || !ref_newer(new_sha1, ref->old_sha1));\n>  \n> +\n>  \t\tif (ref->nonfastforward && !ref->force && !args.force_update) {\n> -\t\t\tref->status = REF_STATUS_REJECT_NONFASTFORWARD;\n> +\t\t\tif (ref_newer(ref->old_sha1, new_sha1))\n> +\t\t\t\tref->status = REF_STATUS_REJECT_REWIND;\n> +\t\t\telse\n> +\t\t\t\tref->status = REF_STATUS_REJECT_NONFASTFORWARD;\n\nIndeed.  I did not think it was that easy, but apparently it is.\n\nThanks,\nDscho\n"},{"id":"68074","messageId":"alpine.LSU.1.00.0802091304440.11591@racer.site","threadId":"11961","inReplyTo":"46a038f90802090350rc4780d1ted60c03b9abf1fc0@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-09T13:06:42Z","receivedAt":"2008-02-09T13:06:42Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Feb 2008, Martin Langhoff wrote:\n\n> And I don't completely follow how bad the impact of\n> auto-fast-forwarding local tracking branches on a merge. If it's a\n> fast-forward, my \"local state\" wasn't that exciting to begin with ;-)\n\nNot necessarily.  Maybe you wanted to work on it, kept your local branch \nas a reminder.  Maybe even reset --hard to a known-bad commit.\n\nThe thing is: local is local is local.  If you muddy the clear \ndistinctions, you will make semantics much harder to grasp.\n\nHaving said that, you _could_ introduce a command line option \n\"--ff-local-branches\", which would keep the semantics clean.\n\nCiao,\nDscho\n"},{"id":"68076","messageId":"alpine.LSU.1.00.0802091307160.11591@racer.site","threadId":"11961","inReplyTo":"6B804F0D-9C3B-46F3-B922-7A5CBEF55522@zib.de","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-09T13:10:21Z","receivedAt":"2008-02-09T13:10:21Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Feb 2008, Steffen Prohaska wrote:\n\n> Personally, I decided it is safer to teach users to explicitly type what \n> they mean.  I'd probably not use the push.onlyHEAD config option.\n> \n> I also proposed that the default could do nothing if no explicit push \n> lines are in the configuration file.  Users would be forced to \n> explicitly type what the want: Either they can say \"--matching\" or they \n> can say \"--current\".  This is similar to the new \"git clean\" default.  \n> But I remember there *was* objection against this because everyone would \n> be forced to type more and different than \"git clean\" the default of \n> \"git push\" is considered \"safe\", so there's no need to protect the user \n> from \"git push\".\n> \n> Junio proposed various possible changes to the configuration variables \n> that could resolve the issues.  I do not remember the details.\n\nThe way would be like this, I think:\n\n- introduce a command line option for push, like \"--push-common-refs\", and \nissue a warning whenever \"git push\" is called without command line \noptions (along the lines \"This default behaviour is deprecated; please use \n--push-common-refs\").\n\n- in a waaaay later version, just take away the default action of \"git \npush\", instead showing the usage.\n\nWe had something similar wit the -i and -o options to \"git commit\".\n\nCiao,\nDscho\n"},{"id":"68080","messageId":"20080209132209.GA20443@coredump.intra.peff.net","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802091302550.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-09T13:22:09Z","receivedAt":"2008-02-09T13:22:09Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 09, 2008 at 01:04:10PM +0000, Johannes Schindelin wrote:\n\n> I was already trying to make a patch on top of yours which says \"[stale]\" \n> instead of \"[rejected]\" for those cases, but then I realised that 2 tests \n> in t5400 fail.\n\nI think the problem is that tests 7/8 in t5400 actually try to create\na non-ff situation by doing a rewind. So it is not a bug in the new code\nso much as the test relied on the very behavior we changed.\n\n> > -\t\t\tref->status = REF_STATUS_REJECT_NONFASTFORWARD;\n> > +\t\t\tif (ref_newer(ref->old_sha1, new_sha1))\n> > +\t\t\t\tref->status = REF_STATUS_REJECT_REWIND;\n> > +\t\t\telse\n> > +\t\t\t\tref->status = REF_STATUS_REJECT_NONFASTFORWARD;\n> \n> Indeed.  I did not think it was that easy, but apparently it is.\n\nIt's also slower than it needs to be, since we also do a ref_newer in\nthe other direction, and because non-ff cases traverse all the way to\nthe root.  I think you could do better to write a function (similar to\nlimit_list) which returned one of { A is an ancestor of B, B is an\nancestor of A, A and B are equal, A and B are not directly related },\nand you would have to traverse down only to the nearest merge base.\n\n-Peff\n"},{"id":"68148","messageId":"7v7ihd7ee1.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802091307160.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-10T02:07:34Z","receivedAt":"2008-02-10T02:07:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> The way would be like this, I think:\n>\n> - introduce a command line option for push, like \"--push-common-refs\", and \n> issue a warning whenever \"git push\" is called without command line \n> options (along the lines \"This default behaviour is deprecated; please use \n> --push-common-refs\").\n>\n> - in a waaaay later version, just take away the default action of \"git \n> push\", instead showing the usage.\n\nI do not think that is a right approach.  To please both camps\nwithout forcing people to\n\n (1) change what they are used to, and\n (2) type overlong command line,\n\nI think the traditional \"matching refs by default\", combined\nwith \"'git push HEAD' defaults to pushing the current branch to\nthe default location\" would be a well balanced compromise.\n"},{"id":"68150","messageId":"alpine.LSU.1.00.0802100213330.11591@racer.site","threadId":"11961","inReplyTo":"7v7ihd7ee1.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T02:15:50Z","receivedAt":"2008-02-10T02:15:50Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Feb 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > The way would be like this, I think:\n> >\n> > - introduce a command line option for push, like \"--push-common-refs\", \n> > and issue a warning whenever \"git push\" is called without command line \n> > options (along the lines \"This default behaviour is deprecated; please \n> > use --push-common-refs\").\n> >\n> > - in a waaaay later version, just take away the default action of \"git \n> > push\", instead showing the usage.\n> \n> I do not think that is a right approach.  To please both camps without \n> forcing people to\n> \n>  (1) change what they are used to, and\n>  (2) type overlong command line,\n> \n> I think the traditional \"matching refs by default\", combined with \"'git \n> push HEAD' defaults to pushing the current branch to the default \n> location\" would be a well balanced compromise.\n\nI'm no longer that sure.  It seems that quite a lot of people do not read \nmanuals, and have no clue what they are doing when they just try\n\n\t$ git push\n\nto see what the synopsis is.\n\nIf there are enough of those people out there, we might want to change our \ndefault action to \"-h\".\n\nYes, that hurts old-timers.  Yes, it's not a perfect world.  No, I don't \nwant to bend over for just a few people.\n\nCiao,\nDscho\n"},{"id":"68151","messageId":"7vwspd5z1d.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"46a038f90802090350rc4780d1ted60c03b9abf1fc0@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-10T02:24:30Z","receivedAt":"2008-02-10T02:24:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Martin Langhoff\" <martin.langhoff@gmail.com> writes:\n\n> Still, the big fat ![rejected] do seem over the top when I know it\n> really means \"stale\".\n\nIf \"stale\" can be proven cheaply, I think it would be a very\ngood change to introduce [rejected] vs [stale].\n\n> And I don't completely follow how bad the impact of\n> auto-fast-forwarding local tracking branches on a merge. If it's a\n> fast-forward, my \"local state\" wasn't that exciting to begin with ;-)\n\nIf your branch is configured to track the remote and when your\nbranch is behind, it probably is safe to assume that the user\nmost likely wants the ff merge to happen _when_ the branch is\nchecked out.  I am with you that.  I am not sure if that ff\nshould happen when you fetch from the other side as you suggest.\n\nDoing so automatically means it would break workflows of people\nwho are deliberately _holding back_ from updating to the remote\nthey are tracking for whatever reason.  As you said, the point\nthey were holding back at can be found as _one_ of the reflog\nentries even if you force the auto-ff upon fetch, but that does\nmean you are forcing them to go and look for it, while they used\nto be able to _rely on_ that their tips will not be molested\nwithout them telling git to do so explicitly.\n\nSo I am with you that auto-ff would help more people but I am\nnot convinced it would not hurt anybody.\n\nPerhaps making \"git-checkout\" to notice this and offer (or\nsuggest) fast-forwarding at that point may be safer and make\nmore sense.  You cannot grow your local branch unless you check\nthem out, and your remote tracking will keep growing without the\nauto-ff you are suggesting, so it is not like people will lose\nanchoring point to compare between branches if we do not\nauto-ff.\n"},{"id":"68161","messageId":"7vd4r55vcs.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"3AA71024-080B-4252-8416-82AE38A4498E@zib.de","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-10T03:44:03Z","receivedAt":"2008-02-10T03:44:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> On Feb 8, 2008, at 8:48 AM, Junio C Hamano wrote:\n>\n>> Perhaps it might make sense to have a checkout hook that notices\n>> the branch that is being checked out is meant to build on top of\n>> a corresponding remote tracking branch, and performs the\n>> necessary fast-forward when that is the case.\n>\n> Or just print a warning that there are new commits on the\n> tracked branch and leave the decision how to proceed to\n> the user?\n\nYeah, that would be even safer.  And I do not mind if the \"git\ncheckout\" learned to do so natively without needing of such a\nhook.\n"},{"id":"68186","messageId":"20080210101353.GA26568@coredump.intra.peff.net","threadId":"11961","inReplyTo":"7vwspd5z1d.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-10T10:13:53Z","receivedAt":"2008-02-10T10:13:53Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 09, 2008 at 06:24:30PM -0800, Junio C Hamano wrote:\n\n> > Still, the big fat ![rejected] do seem over the top when I know it\n> > really means \"stale\".\n> If \"stale\" can be proven cheaply, I think it would be a very\n> good change to introduce [rejected] vs [stale].\n\nI think there is still one problem with that: you are not splitting the\ncases into \"rejected\" and \"stale\". You are splitting them into\n\"rejected, or we didn't have enough information to determine staleness\"\nand \"definitely stale\"[1]. So in the cases that it works perfectly, it may\nbe a useful distinction; but it might end up confusing people when the\nsame situation produces different results depending on what has been\nfetched locally.\n\n-Peff\n\n[1]: Actually, you can further split into \"definitely rejected\",\n\"definitely stale\", and \"undetermined\" but I don't think that is being\nproposed.\n"},{"id":"68187","messageId":"20080210101756.GB26568@coredump.intra.peff.net","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802100213330.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-10T10:17:56Z","receivedAt":"2008-02-10T10:17:56Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 10, 2008 at 02:15:50AM +0000, Johannes Schindelin wrote:\n\n> I'm no longer that sure.  It seems that quite a lot of people do not read \n> manuals, and have no clue what they are doing when they just try\n> \n> \t$ git push\n> \n> to see what the synopsis is.\n> \n> If there are enough of those people out there, we might want to change our \n> default action to \"-h\".\n> \n> Yes, that hurts old-timers.  Yes, it's not a perfect world.  No, I don't \n> want to bend over for just a few people.\n\nI am still not convinced that an option to change the default behavior\nis unreasonable. Yes, it means that \"git push\" will do different things\ndepending on your confi$g. But \"git push\" is a _shorthand_, and if you\nwant to say things definitely, then say them: \"git push --matching\norigin\" or \"git push HEAD\" (assuming that a \"--matching\" option would\nexist to specify what is now the default behavior).\n\n-Peff\n"},{"id":"68199","messageId":"alpine.LSU.1.00.0802101219280.11591@racer.site","threadId":"11961","inReplyTo":"20080210101756.GB26568@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T12:20:23Z","receivedAt":"2008-02-10T12:20:23Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Feb 2008, Jeff King wrote:\n\n> On Sun, Feb 10, 2008 at 02:15:50AM +0000, Johannes Schindelin wrote:\n> \n> > I'm no longer that sure.  It seems that quite a lot of people do not read \n> > manuals, and have no clue what they are doing when they just try\n> > \n> > \t$ git push\n> > \n> > to see what the synopsis is.\n> > \n> > If there are enough of those people out there, we might want to change \n> > our default action to \"-h\".\n> > \n> > Yes, that hurts old-timers.  Yes, it's not a perfect world.  No, I \n> > don't want to bend over for just a few people.\n> \n> I am still not convinced that an option to change the default behavior \n> is unreasonable. Yes, it means that \"git push\" will do different things \n> depending on your confi$g. But \"git push\" is a _shorthand_, and if you \n> want to say things definitely, then say them: \"git push --matching \n> origin\" or \"git push HEAD\" (assuming that a \"--matching\" option would \n> exist to specify what is now the default behavior).\n\nWell, I am not completely opposed to changing the default behaviour, be \nthat showing the synopsis or pushing HEAD to origin.\n\nBut _do_ give old-timers some time to adjust, _if_ you want to change the \ndefault behaviour.\n\nCiao,\nDscho\n"},{"id":"68200","messageId":"alpine.LSU.1.00.0802101220360.11591@racer.site","threadId":"11961","inReplyTo":"7vd4r55vcs.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T12:21:09Z","receivedAt":"2008-02-10T12:21:09Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Feb 2008, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n> \n> > On Feb 8, 2008, at 8:48 AM, Junio C Hamano wrote:\n> >\n> >> Perhaps it might make sense to have a checkout hook that notices\n> >> the branch that is being checked out is meant to build on top of\n> >> a corresponding remote tracking branch, and performs the\n> >> necessary fast-forward when that is the case.\n> >\n> > Or just print a warning that there are new commits on the\n> > tracked branch and leave the decision how to proceed to\n> > the user?\n> \n> Yeah, that would be even safer.  And I do not mind if the \"git\n> checkout\" learned to do so natively without needing of such a\n> hook.\n\nHeh, should be easier when we have builtin git-checkout... which reminds \nme that I have a patch series to review.  ;-)\n\nCiao,\nDscho\n"},{"id":"68201","messageId":"alpine.LSU.1.00.0802101221310.11591@racer.site","threadId":"11961","inReplyTo":"20080210101353.GA26568@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T12:22:27Z","receivedAt":"2008-02-10T12:22:27Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Feb 2008, Jeff King wrote:\n\n> On Sat, Feb 09, 2008 at 06:24:30PM -0800, Junio C Hamano wrote:\n> \n> > > Still, the big fat ![rejected] do seem over the top when I know it \n> > > really means \"stale\".\n> >\n> > If \"stale\" can be proven cheaply, I think it would be a very good \n> > change to introduce [rejected] vs [stale].\n> \n> I think there is still one problem with that: you are not splitting the\n> cases into \"rejected\" and \"stale\".\n\nFWIW I think it is perfectly reasonable to say \"stale\" when you _know_ \nthat it's stale, and \"rejected\" when you don't know the reason.\n\nCiao,\nDscho\n"},{"id":"68202","messageId":"20080210122321.GA31009@coredump.intra.peff.net","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802101219280.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-10T12:23:21Z","receivedAt":"2008-02-10T12:23:21Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 10, 2008 at 12:20:23PM +0000, Johannes Schindelin wrote:\n\n> > I am still not convinced that an option to change the default behavior \n> > is unreasonable. Yes, it means that \"git push\" will do different things \n> > depending on your confi$g. But \"git push\" is a _shorthand_, and if you \n> > want to say things definitely, then say them: \"git push --matching \n> > origin\" or \"git push HEAD\" (assuming that a \"--matching\" option would \n> > exist to specify what is now the default behavior).\n> \n> Well, I am not completely opposed to changing the default behaviour, be \n> that showing the synopsis or pushing HEAD to origin.\n> \n> But _do_ give old-timers some time to adjust, _if_ you want to change the \n> default behaviour.\n\nSorry, I should have been more clear. By \"default\" I mean \"what happens\nwhen you type \"git push\" not \"the behavior with no config options set.\"\n\nIOW, I am not necessarily proposing to change the default for\nold-timers, but rather to allow differing behavior for \"git push\"\nwithout remote depending on a config variable. So different behavior for\ndifferent people.\n\n-Peff\n"},{"id":"68207","messageId":"alpine.LSU.1.00.0802101303140.11591@racer.site","threadId":"11961","inReplyTo":"20080210122321.GA31009@coredump.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T13:04:03Z","receivedAt":"2008-02-10T13:04:03Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Feb 2008, Jeff King wrote:\n\n> IOW, I am not necessarily proposing to change the default for \n> old-timers, but rather to allow differing behavior for \"git push\" \n> without remote depending on a config variable. So different behavior for \n> different people.\n\nHmm.  So that means that if an old-timer comes to help to a new-comer, \nthe old-timer will be surprised?\n\nYou know I am a fan of consistency, so you know I cannot agree to your \nsuggestion.\n\nCiao,\nDscho\n"},{"id":"68208","messageId":"20080210130718.GA1005@coredump.intra.peff.net","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802101303140.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-10T13:07:18Z","receivedAt":"2008-02-10T13:07:18Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 10, 2008 at 01:04:03PM +0000, Johannes Schindelin wrote:\n\n> > IOW, I am not necessarily proposing to change the default for \n> > old-timers, but rather to allow differing behavior for \"git push\" \n> > without remote depending on a config variable. So different behavior for \n> > different people.\n> \n> Hmm.  So that means that if an old-timer comes to help to a new-comer, \n> the old-timer will be surprised?\n\nNo, the old-timer will type what he means: \"git push --matching origin\"\nor \"git push origin refspec\".\n\n> You know I am a fan of consistency, so you know I cannot agree to your \n> suggestion.\n\nI suspected you would say that. I agree that consistency has value, but\nit can also get in the way when there really are two equally valid\napproaches, and both should be available.\n\n-Peff\n"},{"id":"68214","messageId":"0DE4061C-7189-4932-AA3D-D09009F753F2@wincent.com","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802100213330.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2008-02-10T14:03:13Z","receivedAt":"2008-02-10T14:03:13Z","isPatch":false,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 10/2/2008, a las 3:15, Johannes Schindelin escribió:\n\n> I'm no longer that sure.  It seems that quite a lot of people do not  \n> read\n> manuals, and have no clue what they are doing when they just try\n>\n> \t$ git push\n>\n> to see what the synopsis is.\n\nI think there's no way we should be catering for people who type  \ncommand like \"git push\" just to see what the synopsis does.\n\nThe verb \"push\" very clearly has connotations of a state-changing,  \npossibly irreversible action (unlike other verbs like \"log\" or \"show\").\n\nPeople who type \"git push\" just to see a synopsis need to learn a  \nlesson; the lesson being that if you want to find out what a command  \ndoes the safest thing is to type \"git help push\" instead.\n\nCheers,\nWincent\n"},{"id":"68215","messageId":"20080210150216.GB8797@dervierte","threadId":"11961","inReplyTo":"0DE4061C-7189-4932-AA3D-D09009F753F2@wincent.com","subject":"Re: Minor annoyance with git push","fromName":"Steven Walter","fromEmail":"stevenrwalter@gmail.com","sentAt":"2008-02-10T15:02:17Z","receivedAt":"2008-02-10T15:02:17Z","isPatch":false,"sender":{"key":"stevenrwalter@gmail.com","avatar":"https://avatars.githubusercontent.com/u/79127?v=4"},"body":"On Sun, Feb 10, 2008 at 03:03:13PM +0100, Wincent Colaiuta wrote:\n> I think there's no way we should be catering for people who type command \n> like \"git push\" just to see what the synopsis does.\n>\n> The verb \"push\" very clearly has connotations of a state-changing, possibly \n> irreversible action (unlike other verbs like \"log\" or \"show\").\n\nI think you're quite correct: push is a state changing action.  For that\nreason, it should default to the smallest amount of work conceivably\nenvisioned by the user.  To do more work than the user may have meant is\nasking for trouble.\n\nTake git-commit as a parallel.  You make some file changes and run\n\"git commit\".  Nothing happens.  If you wanted to commit all your\nchanges, you need the -a flag.  Here, subversion takes the opposite\napproach and commits all your files, when in fact you may have only\nwanted a smaller subset.  I have seen this cause problems many times\n(and more than once, I was the problem-maker :) )\n\n> People who type \"git push\" just to see a synopsis need to learn a lesson; \n> the lesson being that if you want to find out what a command does the \n> safest thing is to type \"git help push\" instead.\n\nThis is an interesting theory on user-interface design.\n\n\nI propose a new configuration option, remote.*.pushAllRefs, defaulting\nto off.  When pushAllRefs is false, \"git push\" pushes only the current\nbranch.  When pushAllRefs is true, \"git push\" does what it does today.\nFor the old-timers, the impact of such a change seems minimal.\nWorst-case, they run \"git push,\" it doesn't do what they expect, they run\n\"git push origin\" and then go change their config files.\n\nThoughts?\n-- \n-Steven Walter <stevenrwalter@gmail.com>\nFreedom is the freedom to say that 2 + 2 = 4\nB2F1 0ECC E605 7321 E818  7A65 FC81 9777 DC28 9E8F \n"},{"id":"68221","messageId":"alpine.LSU.1.00.0802101625200.11591@racer.site","threadId":"11961","inReplyTo":"0DE4061C-7189-4932-AA3D-D09009F753F2@wincent.com","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T16:26:11Z","receivedAt":"2008-02-10T16:26:11Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Feb 2008, Wincent Colaiuta wrote:\n\n> El 10/2/2008, a las 3:15, Johannes Schindelin escribió:\n> \n> > I'm no longer that sure.  It seems that quite a lot of people do not \n> > read manuals, and have no clue what they are doing when they just try\n> > \n> > \t$ git push\n> > \n> > to see what the synopsis is.\n> \n> I think there's no way we should be catering for people who type command \n> like \"git push\" just to see what the synopsis does.\n> \n> The verb \"push\" very clearly has connotations of a state-changing, \n> possibly irreversible action (unlike other verbs like \"log\" or \"show\").\n\nThe problem is that \"push\" alone does not really imply which kind of push.\n\nBesides, not everybody can be expected to be such an uber-git as you and \nme.\n\nCiao,\nDscho\n"},{"id":"68223","messageId":"alpine.LSU.1.00.0802101626201.11591@racer.site","threadId":"11961","inReplyTo":"20080210150216.GB8797@dervierte","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-10T16:29:31Z","receivedAt":"2008-02-10T16:29:31Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 10 Feb 2008, Steven Walter wrote:\n\n> I propose a new configuration option, remote.*.pushAllRefs, defaulting \n> to off.  When pushAllRefs is false, \"git push\" pushes only the current \n> branch.  When pushAllRefs is true, \"git push\" does what it does today. \n> For the old-timers, the impact of such a change seems minimal. \n> Worst-case, they run \"git push,\" it doesn't do what they expect, they \n> run \"git push origin\" and then go change their config files.\n\nI don't like it.\n\nThis would mean that I would have to look into the config everytime before \nI push, to be sure what semantics the push has in _this_ repository.\n\n_If_ we change git-push's default behaviour, we have to introduce an \noption to do what the default action is now, _first_!\n\nAnd _then_ we can start discussing what the default action should be, and \nI tend to think that it would make sense to default to the synopsis.\n\nBut that comes _second_, and we'd have to agree on _one_ course of action.\n\nI mean, if you do not like the default behaviour of git-push now, you can \nalways introduce an alias, if you want repository/host-specific actions.\n\nCiao,\nDscho\n"},{"id":"68242","messageId":"07136779-23EB-4DAA-84C3-D54B7AC029AB@wincent.com","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802101625200.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2008-02-10T18:18:24Z","receivedAt":"2008-02-10T18:18:24Z","isPatch":false,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 10/2/2008, a las 17:26, Johannes Schindelin escribió:\n\n> On Sun, 10 Feb 2008, Wincent Colaiuta wrote:\n>\n>> El 10/2/2008, a las 3:15, Johannes Schindelin escribió:\n>>\n>>> I'm no longer that sure.  It seems that quite a lot of people do not\n>>> read manuals, and have no clue what they are doing when they just  \n>>> try\n>>>\n>>> \t$ git push\n>>>\n>>> to see what the synopsis is.\n>>\n>> I think there's no way we should be catering for people who type  \n>> command\n>> like \"git push\" just to see what the synopsis does.\n>>\n>> The verb \"push\" very clearly has connotations of a state-changing,\n>> possibly irreversible action (unlike other verbs like \"log\" or  \n>> \"show\").\n>\n> The problem is that \"push\" alone does not really imply which kind of  \n> push.\n\nYes, I know. I myself was surprised by the default behaviour the first  \ntime I used \"git push\" (I only expected it to push the branch I was  \ncurrently on).\n\nBut my point is that if you don't know what \"git push\" is going to do  \nbecause its name doesn't imply \"which kind of push\" it will do (and in  \nreality a newcomer might not even realize that there might be more  \nthan one kind of push), then adopting a \"try it and see\" approach  \n(\"let's type 'git push' and see if it gives me a synopsis\") is not a  \nvery good idea, and in a case like this where \"push\" is what I'd call  \na \"strong\" verb, I don't think we should be trying to protect the user  \nfrom doing something obviously idiotic.\n\nI'm all for protecting the user from nasty surprises (like \"git  \nclean\"; \"clean\" doesn't sound nearly as destructive as it can actually  \nturn out to be) but I don't think that anyone typing \"git push\" can  \nfairly claim to be surprised when Git goes ahead and, er, pushes  \nsomething.\n\nCheers,\nWincent\n"},{"id":"68286","messageId":"20080210223440.GA15051@sigill.intra.peff.net","threadId":"11961","inReplyTo":"07136779-23EB-4DAA-84C3-D54B7AC029AB@wincent.com","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-10T22:34:40Z","receivedAt":"2008-02-10T22:34:40Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 10, 2008 at 07:18:24PM +0100, Wincent Colaiuta wrote:\n\n> I'm all for protecting the user from nasty surprises (like \"git clean\"; \n> \"clean\" doesn't sound nearly as destructive as it can actually turn out to \n> be) but I don't think that anyone typing \"git push\" can fairly claim to be \n> surprised when Git goes ahead and, er, pushes something.\n\nI don't think people are surprised that \"git push\" pushes something. I\nthink they are surprised that \"git push\" makes changes based on non-HEAD\nbranches (which may or may not be in a useful state). Are there any\nother git commands which use non-HEAD branches that have not been\nexplicitly mentioned by the user?  I can think only of query-type\ncommands (like show-branch, or describe) that are non-state-changing.\n\nI think what is problematic here is that push makes changes based on\nstate that is irrelevant to most git actions. Thus you have things like\nMartin's complaint: \"what, why are you rejecting branch foo? I haven't\neven worked on that in months.\" He is expected to either remember the\nstate of all branches in his repository, or to keep it extremely tidy\n(either deleting branches immediately after use, or keeping them up to\ndate with upstream, which is extra useless work from his perspective).\n\n-Peff\n"},{"id":"68289","messageId":"7vzlu8cta1.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"20080210223440.GA15051@sigill.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-10T22:59:18Z","receivedAt":"2008-02-10T22:59:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> ... Are there any\n> other git commands which use non-HEAD branches that have not been\n> explicitly mentioned by the user?  I can think only of query-type\n> commands (like show-branch, or describe) that are non-state-changing.\n\nThat's an irrelevant comparison.  push and fetch have always\nbeen multi-branch operations by default from day one.  The issue\nis not HEAD vs non-HEAD.\n\nYou can argue that historically established practices do not\nmatter at all (at least to new people), and I'd grant that it\nmay be a valid argument.  But a change that breaks existing\npractices needs to be sold much more carefully.  I still do not\nunderstand what the opposition is to keep the current behaviour\nas the default and have a shorthand for the single head push\naccessible with a short and sweet \"git push $there HEAD\" (and\ndefault $there to 'origin' when missing).\n\nIf you are introducing a new behaviour, there is no way the new\nbehaviour can start out by replacing the longtime default.  It\nshould start out as an option, and if it is a commonly useful\noption then make it an _easily accessible_ option.  And accept\nsuch an _enhancement_ sooner to help people who want such a\nbehaviour sooner.  That would not hurt anybody but help\n(hopefully) many people, without downside.\n\nSwitching the default behaviour is a much longer term thing.  It\ndefinitely has downside people mentioned in this thread.\n"},{"id":"68291","messageId":"20080210232911.GA15313@sigill.intra.peff.net","threadId":"11961","inReplyTo":"7vzlu8cta1.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-10T23:29:11Z","receivedAt":"2008-02-10T23:29:11Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 10, 2008 at 02:59:18PM -0800, Junio C Hamano wrote:\n\n> > ... Are there any\n> > other git commands which use non-HEAD branches that have not been\n> > explicitly mentioned by the user?  I can think only of query-type\n> > commands (like show-branch, or describe) that are non-state-changing.\n> \n> That's an irrelevant comparison.  push and fetch have always\n> been multi-branch operations by default from day one.  The issue\n> is not HEAD vs non-HEAD.\n\nI think \"irrelevant\" here is in the eye of the beholder. If you are\ncoming from the perspective of \"historical behavior\" then the current\nbehavior makes sense. If you are coming from the perspective of a user\nwho does not typically do a lot of branching, then the behavior can be\nsurprising. And I think there is anecdotal evidence that some users _do_\nfind this surprising. I have personally seen it, and I think even an\nexperienced user like Martin is finding the behavior non-intuitive.\n\n> You can argue that historically established practices do not\n> matter at all (at least to new people), and I'd grant that it\n> may be a valid argument.  But a change that breaks existing\n> practices needs to be sold much more carefully.  I still do not\n\nAgreed.\n\n> understand what the opposition is to keep the current behaviour\n> as the default and have a shorthand for the single head push\n> accessible with a short and sweet \"git push $there HEAD\" (and\n> default $there to 'origin' when missing).\n\nI think the problem is that you are asking people with particular\nworkflows to always remember to type something extra, and if they\nforget, you punish them by doing a potentially destructive operation\n(although admittedly, it is destructive only if you happen to be using\n\"-f\").\n\n> If you are introducing a new behaviour, there is no way the new\n> behaviour can start out by replacing the longtime default.  It\n> should start out as an option, and if it is a commonly useful\n> option then make it an _easily accessible_ option.  And accept\n> such an _enhancement_ sooner to help people who want such a\n> behaviour sooner.  That would not hurt anybody but help\n> (hopefully) many people, without downside.\n\nI think we already have that option (as you mentioned): \"git push $there\nHEAD\". We can make it more easily accessible (as you have proposed):\n\"git push HEAD\" (though I still have some reservations about that). But\nnone of that changes the fact that for some people's workflows, they\nwill _always_ have to remember to add extra magic to the command line.\n\nWhat I have proposed is adding a config option to make that option even\nmore easily accessible. The only argument I have seen against that is\n\"some users can't use other users' git setup\". While this is a downside,\nI think this uncommon situation is outweighed by the very common\nsituation of users using their _own_ git setups.\n\nIOW, such an option makes a tradeoff. Users helping other users must\nexplicitly say what they mean: \"git push --matching\" or \"git push $there\nHEAD\". But users using their own setups can use the shorthand \"git push\"\nto do what is most useful for their workflow. And I think we should\noptimize for the latter case, as it is much more common.\n\n-Peff\n"},{"id":"68945","messageId":"7vfxvs75kp.fsf_-_@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"7vwspd5z1d.fsf@gitster.siamese.dyndns.org","subject":"[RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-17T01:08:22Z","receivedAt":"2008-02-17T01:08:22Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Perhaps making \"git-checkout\" to notice this and offer (or\n> suggest) fast-forwarding at that point may be safer and make\n> more sense.  You cannot grow your local branch unless you check\n> them out, and your remote tracking will keep growing without the\n> auto-ff you are suggesting, so it is not like people will lose\n> anchoring point to compare between branches if we do not\n> auto-ff.\n\nSo I did this.\n\nWhen you are switching to a branch that is marked to merge from\nsomewhere else, e.g. when you have:\n\n    [branch \"next\"]\n            remote = upstream\n            merge = refs/heads/next\n    [remote \"upstream\"]\n            url = ...\n            fetch = refs/heads/*:refs/remotes/linus/*\n\nand you say \"git checkout next\", then after we switch the branch\nwe check the upstream (in this case, refs/remotes/linus/next)\nand our branch, and:\n\n    (1) if they match, nothing happens;\n\n    (2) if you are ahead (i.e. the upstream is a strict ancestor\n        of you), one line message tells you so;\n\n    (3) otherwise, you are either behind or you and the upstream\n        have forked.  One line message will tell you which and\n        then you will see a \"log --pretty=oneline --left-right\".\n\nWe could enhance this with an option that tells the command to\ncheck if there is no local change, and automatically fast\nforward when you are truly behind.  But I ripped out that change\nbecause I was unsure what the right way should be to allow users\nto control it (issues include that checkout should not become\nautomatically interactive).\n\nThis is hot off the press and I know it tends to be a bit too\nloud.  It is based on Daniel's \"git checkout in C\" with Dscho's\nlock_file fix.\n\n---\n\n builtin-checkout.c |  136 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 136 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 59a0ef4..9370ba0 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -12,6 +12,7 @@\n #include \"branch.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n+#include \"remote.h\"\n \n static const char * const checkout_usage[] = {\n \t\"git checkout [options] <branch>\",\n@@ -290,6 +291,139 @@ static int merge_working_tree(struct checkout_opts *opts,\n \treturn 0;\n }\n \n+/*\n+ * We really should allow cb_data... Yuck\n+ */\n+static const char *branch_name;\n+static int branch_name_len;\n+static char *found_remote;\n+static char *found_merge;\n+static int read_branch_config(const char *var, const char *value)\n+{\n+\tconst char *name;\n+\tif (prefixcmp(var, \"branch.\"))\n+\t\treturn 0; /* not ours */\n+\tname = var + strlen(\"branch.\");\n+\tif (strncmp(name, branch_name, branch_name_len) ||\n+\t    name[branch_name_len] != '.')\n+\t\treturn 0; /* not ours either */\n+\tif (!strcmp(name + branch_name_len, \".remote\")) {\n+\t\t/*\n+\t\t * Yeah, I know Christian's clean-up should\n+\t\t * be used here, but the topic is based on an\n+\t\t * older fork point.\n+\t\t */\n+\t\tif (!value)\n+\t\t\treturn error(\"'%s' not string\", var);\n+\t\tfound_remote = xstrdup(value);\n+\t\treturn 0;\n+\t}\n+\tif (!strcmp(name + branch_name_len, \".merge\")) {\n+\t\tif (!value)\n+\t\t\treturn error(\"'%s' not string\", var);\n+\t\tfound_merge = xstrdup(value);\n+\t\treturn 0;\n+\t}\n+\treturn 0; /* not ours */\n+}\n+\n+static int find_build_base(const char *ours, char **base)\n+{\n+\tstruct remote *remote;\n+\tstruct refspec spec;\n+\n+\t*base = NULL;\n+\n+\tbranch_name = ours + strlen(\"refs/heads/\");\n+\tbranch_name_len = strlen(branch_name);\n+\tfound_remote = NULL;\n+\tfound_merge = NULL;\n+\tgit_config(read_branch_config);\n+\n+\tif (!found_remote || !found_merge) {\n+\tcleanup:\n+\t\tfree(found_remote);\n+\t\tfree(found_merge);\n+\t\treturn 0;\n+\t}\n+\n+\tremote = remote_get(found_remote);\n+\tmemset(&spec, 0, sizeof(spec));\n+\tspec.src = found_merge;\n+\tif (remote_find_tracking(remote, &spec))\n+\t\tgoto cleanup;\n+\t*base = spec.dst;\n+\treturn 1;\n+}\n+\n+static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)\n+{\n+\t/*\n+\t * We have switched to a new branch; is it building on\n+\t * top of another branch, and if so does that other branch\n+\t * have changes we do not have yet?\n+\t */\n+\tchar *base;\n+\tunsigned char sha1[20];\n+\tstruct commit *ours, *theirs;\n+\tconst char *msgfmt;\n+\tchar symmetric[84];\n+\tint show_log;\n+\n+\tif (!resolve_ref(new->path, sha1, 1, NULL))\n+\t\treturn;\n+\tours = lookup_commit(sha1);\n+\n+\tif (!find_build_base(new->path, &base))\n+\t\treturn;\n+\n+\tsprintf(symmetric, \"%s\", sha1_to_hex(sha1));\n+\n+\t/*\n+\t * Ok, it is tracking base; is it ahead of us?\n+\t */\n+\tif (!resolve_ref(base, sha1, 1, NULL))\n+\t\treturn;\n+\ttheirs = lookup_commit(sha1);\n+\n+\tsprintf(symmetric + 40, \"...%s\", sha1_to_hex(sha1));\n+\n+\tif (!hashcmp(sha1, ours->object.sha1))\n+\t\treturn; /* we are the same */\n+\n+\tshow_log = 1;\n+\tif (in_merge_bases(theirs, &ours, 1)) {\n+\t\tmsgfmt = \"You are ahead of the tracked branch '%s'\\n\";\n+\t\tshow_log = 0;\n+\t}\n+\telse if (in_merge_bases(ours, &theirs, 1))\n+\t\tmsgfmt = \"Your branch can be fast-forwarded to the tracked branch '%s'\\n\";\n+\telse\n+\t\tmsgfmt = \"Both your branch and the tracked branch '%s' have own changes, you would eventually need to merge\\n\";\n+\n+\tif (!prefixcmp(base, \"refs/remotes/\"))\n+\t\tbase += strlen(\"refs/remotes/\");\n+\tfprintf(stderr, msgfmt, base);\n+\n+\tif (show_log) {\n+\t\tconst char *args[32];\n+\t\tint ac;\n+\n+\t\tac = 0;\n+\t\targs[ac++] = \"log\";\n+\t\targs[ac++] = \"--pretty=oneline\";\n+\t\targs[ac++] = \"--abbrev-commit\";\n+\t\targs[ac++] = \"--left-right\";\n+\t\targs[ac++] = \"--boundary\";\n+\t\targs[ac++] = symmetric;\n+\t\targs[ac++] = \"--\";\n+\t\targs[ac] = NULL;\n+\n+\t\trun_command_v_opt(args, RUN_GIT_CMD);\n+\t}\n+}\n+\n+\n static void update_refs_for_switch(struct checkout_opts *opts,\n \t\t\t\t   struct branch_info *old,\n \t\t\t\t   struct branch_info *new)\n@@ -332,6 +466,8 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n \t}\n \tremove_branch_state();\n \tstrbuf_release(&msg);\n+\tif (new->path)\n+\t\tadjust_to_tracking(new, opts);\n }\n \n static int switch_branches(struct checkout_opts *opts,\n"},{"id":"68947","messageId":"alpine.LNX.1.00.0802162202310.5496@iabervon.org","threadId":"11961","inReplyTo":"7vfxvs75kp.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-02-17T03:31:26Z","receivedAt":"2008-02-17T03:31:26Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 16 Feb 2008, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > Perhaps making \"git-checkout\" to notice this and offer (or\n> > suggest) fast-forwarding at that point may be safer and make\n> > more sense.  You cannot grow your local branch unless you check\n> > them out, and your remote tracking will keep growing without the\n> > auto-ff you are suggesting, so it is not like people will lose\n> > anchoring point to compare between branches if we do not\n> > auto-ff.\n> \n> So I did this.\n> \n> When you are switching to a branch that is marked to merge from\n> somewhere else, e.g. when you have:\n> \n>     [branch \"next\"]\n>             remote = upstream\n>             merge = refs/heads/next\n>     [remote \"upstream\"]\n>             url = ...\n>             fetch = refs/heads/*:refs/remotes/linus/*\n> \n> and you say \"git checkout next\", then after we switch the branch\n> we check the upstream (in this case, refs/remotes/linus/next)\n> and our branch, and:\n> \n>     (1) if they match, nothing happens;\n> \n>     (2) if you are ahead (i.e. the upstream is a strict ancestor\n>         of you), one line message tells you so;\n> \n>     (3) otherwise, you are either behind or you and the upstream\n>         have forked.  One line message will tell you which and\n>         then you will see a \"log --pretty=oneline --left-right\".\n\nI like this idea a lot. I'd actually also like it for commit, although (1) \nand (3a) obviously don't happen there. It would help to combat my tendency \nto forget to push when I mean to.\n\nNote that, in addition to \"should I merge before starting to work now\", \nthis also answers \"if I turn off this computer, what can't I get at\".\n\n> We could enhance this with an option that tells the command to\n> check if there is no local change, and automatically fast\n> forward when you are truly behind.  But I ripped out that change\n> because I was unsure what the right way should be to allow users\n> to control it (issues include that checkout should not become\n> automatically interactive).\n\nI suppose you could use a config option to enable it per-branch.\n\nIt would be really clever to make it happen if you do:\n\n$ git checkout next\n(fast-forward info)\n$ git checkout\n\nBut that's probably a bit too clever.\n\n> diff --git a/builtin-checkout.c b/builtin-checkout.c\n> index 59a0ef4..9370ba0 100644\n> --- a/builtin-checkout.c\n> +++ b/builtin-checkout.c\n> @@ -12,6 +12,7 @@\n>  #include \"branch.h\"\n>  #include \"diff.h\"\n>  #include \"revision.h\"\n> +#include \"remote.h\"\n>  \n>  static const char * const checkout_usage[] = {\n>  \t\"git checkout [options] <branch>\",\n> @@ -290,6 +291,139 @@ static int merge_working_tree(struct checkout_opts *opts,\n>  \treturn 0;\n>  }\n>  \n> +/*\n> + * We really should allow cb_data... Yuck\n> + */\n> +static const char *branch_name;\n> +static int branch_name_len;\n> +static char *found_remote;\n> +static char *found_merge;\n> +static int read_branch_config(const char *var, const char *value)\n> +{\n\n...\n\nI think you want branch_get(), which handles all the config file stuff up \nto approximately here:\n\n> +\tremote = remote_get(found_remote);\n> +\tmemset(&spec, 0, sizeof(spec));\n> +\tspec.src = found_merge;\n> +\tif (remote_find_tracking(remote, &spec))\n> +\t\tgoto cleanup;\n> +\t*base = spec.dst;\n> +\treturn 1;\n> +}\n> +\n> +static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)\n> +{\n> +\t/*\n> +\t * We have switched to a new branch; is it building on\n> +\t * top of another branch, and if so does that other branch\n> +\t * have changes we do not have yet?\n> +\t */\n> +\tchar *base;\n> +\tunsigned char sha1[20];\n> +\tstruct commit *ours, *theirs;\n> +\tconst char *msgfmt;\n> +\tchar symmetric[84];\n> +\tint show_log;\n> +\n> +\tif (!resolve_ref(new->path, sha1, 1, NULL))\n> +\t\treturn;\n> +\tours = lookup_commit(sha1);\n> +\n> +\tif (!find_build_base(new->path, &base))\n> +\t\treturn;\n> +\n> +\tsprintf(symmetric, \"%s\", sha1_to_hex(sha1));\n> +\n> +\t/*\n> +\t * Ok, it is tracking base; is it ahead of us?\n> +\t */\n> +\tif (!resolve_ref(base, sha1, 1, NULL))\n> +\t\treturn;\n> +\ttheirs = lookup_commit(sha1);\n> +\n> +\tsprintf(symmetric + 40, \"...%s\", sha1_to_hex(sha1));\n> +\n> +\tif (!hashcmp(sha1, ours->object.sha1))\n> +\t\treturn; /* we are the same */\n> +\n> +\tshow_log = 1;\n> +\tif (in_merge_bases(theirs, &ours, 1)) {\n> +\t\tmsgfmt = \"You are ahead of the tracked branch '%s'\\n\";\n> +\t\tshow_log = 0;\n> +\t}\n> +\telse if (in_merge_bases(ours, &theirs, 1))\n> +\t\tmsgfmt = \"Your branch can be fast-forwarded to the tracked branch '%s'\\n\";\n> +\telse\n> +\t\tmsgfmt = \"Both your branch and the tracked branch '%s' have own changes, you would eventually need to merge\\n\";\n> +\n> +\tif (!prefixcmp(base, \"refs/remotes/\"))\n> +\t\tbase += strlen(\"refs/remotes/\");\n> +\tfprintf(stderr, msgfmt, base);\n> +\n> +\tif (show_log) {\n> +\t\tconst char *args[32];\n> +\t\tint ac;\n> +\n> +\t\tac = 0;\n> +\t\targs[ac++] = \"log\";\n> +\t\targs[ac++] = \"--pretty=oneline\";\n> +\t\targs[ac++] = \"--abbrev-commit\";\n> +\t\targs[ac++] = \"--left-right\";\n> +\t\targs[ac++] = \"--boundary\";\n> +\t\targs[ac++] = symmetric;\n> +\t\targs[ac++] = \"--\";\n> +\t\targs[ac] = NULL;\n> +\n> +\t\trun_command_v_opt(args, RUN_GIT_CMD);\n\nWe really should be able to do this in-process, although I'm not sure if \nwe really can. I don't think I've marked up the history in \nbuiltin-checkout for anything else yet, anyway.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"68951","messageId":"7v4pc843yg.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"alpine.LNX.1.00.0802162202310.5496@iabervon.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-17T04:11:35Z","receivedAt":"2008-02-17T04:11:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n> I like this idea a lot. I'd actually also like it for commit, although (1) \n> and (3a) obviously don't happen there. It would help to combat my tendency \n> to forget to push when I mean to.\n\nThanks.\n\n>> +/*\n>> + * We really should allow cb_data... Yuck\n>> + */\n>> +static const char *branch_name;\n>> +static int branch_name_len;\n>> +static char *found_remote;\n>> +static char *found_merge;\n>> +static int read_branch_config(const char *var, const char *value)\n>> +{\n>\n> ...\n>\n> I think you want branch_get(), which handles all the config file stuff up \n> to approximately here:\n\nFixups are very much welcomed.  This was more or less a proof of\nconcept.\n\n>> +\tif (show_log) {\n>> +\t\tconst char *args[32];\n>> +\t\tint ac;\n>> +\n>> +\t\tac = 0;\n>> +\t\targs[ac++] = \"log\";\n>> +\t\targs[ac++] = \"--pretty=oneline\";\n>> +\t\targs[ac++] = \"--abbrev-commit\";\n>> +\t\targs[ac++] = \"--left-right\";\n>> +\t\targs[ac++] = \"--boundary\";\n>> +\t\targs[ac++] = symmetric;\n>> +\t\targs[ac++] = \"--\";\n>> +\t\targs[ac] = NULL;\n>> +\n>> +\t\trun_command_v_opt(args, RUN_GIT_CMD);\n>\n> We really should be able to do this in-process, although I'm not sure if \n> we really can.\n\nThe code runs in_merge_bases() twice, between our branch head\nand the base, but if we really care about the performance, we\ncan have a single merge-base traversal and the resulting object\npool will have everything necessary to emit the log output\nwithout a separate traversal.\n\nBecause I think that is reasonably easy, I just did not bother\nto.  This is not a performance critical piece of code anyway.\n\nOne thing I thought about was to limit the output to latest N\nentries from both sides.  That would also be easier to implement\nif we do a single merge-base traversal and reuse the result.\n"},{"id":"68952","messageId":"alpine.LNX.1.00.0802170114440.5496@iabervon.org","threadId":"11961","inReplyTo":"7v4pc843yg.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-02-17T06:39:27Z","receivedAt":"2008-02-17T06:39:27Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 16 Feb 2008, Junio C Hamano wrote:\n\n> Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> > I like this idea a lot. I'd actually also like it for commit, although (1) \n> > and (3a) obviously don't happen there. It would help to combat my tendency \n> > to forget to push when I mean to.\n> \n> Thanks.\n> \n> >> +/*\n> >> + * We really should allow cb_data... Yuck\n> >> + */\n> >> +static const char *branch_name;\n> >> +static int branch_name_len;\n> >> +static char *found_remote;\n> >> +static char *found_merge;\n> >> +static int read_branch_config(const char *var, const char *value)\n> >> +{\n> >\n> > ...\n> >\n> > I think you want branch_get(), which handles all the config file stuff up \n> > to approximately here:\n> \n> Fixups are very much welcomed.  This was more or less a proof of\n> concept.\n\nI'm also in part worried about the lack of publicity \"struct branch\" has \ngotten; it would have saved you having to write 64 of 136 lines, so it's \nworth you knowing about.\n\n> >> +\tif (show_log) {\n> >> +\t\tconst char *args[32];\n> >> +\t\tint ac;\n> >> +\n> >> +\t\tac = 0;\n> >> +\t\targs[ac++] = \"log\";\n> >> +\t\targs[ac++] = \"--pretty=oneline\";\n> >> +\t\targs[ac++] = \"--abbrev-commit\";\n> >> +\t\targs[ac++] = \"--left-right\";\n> >> +\t\targs[ac++] = \"--boundary\";\n> >> +\t\targs[ac++] = symmetric;\n> >> +\t\targs[ac++] = \"--\";\n> >> +\t\targs[ac] = NULL;\n> >> +\n> >> +\t\trun_command_v_opt(args, RUN_GIT_CMD);\n> >\n> > We really should be able to do this in-process, although I'm not sure if \n> > we really can.\n> \n> The code runs in_merge_bases() twice, between our branch head\n> and the base, but if we really care about the performance, we\n> can have a single merge-base traversal and the resulting object\n> pool will have everything necessary to emit the log output\n> without a separate traversal.\n> \n> Because I think that is reasonably easy, I just did not bother\n> to.  This is not a performance critical piece of code anyway.\n> \n> One thing I thought about was to limit the output to latest N\n> entries from both sides.  That would also be easier to implement\n> if we do a single merge-base traversal and reuse the result.\n\nYeah, the real advantage to doing it in-process is being able to give a \nparticularly useful overview. Also, I think spawning a pager for it is \ndistracting.\n\nI've also got a change to make it do this report for \"git checkout\" and \n\"git checkout HEAD\" so you can find out if the current branch needs \nanything, but I want to look at it again while not so sleepy before \nsending it, and also write some tests.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"68954","messageId":"7vy79k2fus.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"alpine.LNX.1.00.0802170114440.5496@iabervon.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-17T07:37:31Z","receivedAt":"2008-02-17T07:37:31Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n> I'm also in part worried about the lack of publicity \"struct branch\" has \n> gotten; it would have saved you having to write 64 of 136 lines, so it's \n> worth you knowing about.\n\nActually, I initially took a look at branch.h and tried to reuse\nfind_tracked_branch() but then realized it was a wrong interface.\nThe \"struct branch\" in remote.h (Heh) looks like the right\ninterface.\n\nDocumentation/technical/api-*.txt should really talk about\nwhat's in remote.c.\n"},{"id":"68979","messageId":"20080217122815.GA26031@sigill.intra.peff.net","threadId":"11961","inReplyTo":"7vfxvs75kp.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-17T12:28:15Z","receivedAt":"2008-02-17T12:28:15Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 16, 2008 at 05:08:22PM -0800, Junio C Hamano wrote:\n\n> and you say \"git checkout next\", then after we switch the branch\n> we check the upstream (in this case, refs/remotes/linus/next)\n> and our branch, and:\n> \n>     (1) if they match, nothing happens;\n> \n>     (2) if you are ahead (i.e. the upstream is a strict ancestor\n>         of you), one line message tells you so;\n> \n>     (3) otherwise, you are either behind or you and the upstream\n>         have forked.  One line message will tell you which and\n>         then you will see a \"log --pretty=oneline --left-right\".\n\nOverall I think this is a sensible idea. For (3), it probably makes\nsense to limit the output in some cases. If I checkout a topic branch\nthat I haven't looked at in a few days or even weeks, I am going to get\nspammed with hundreds of commits.\n\nMost of the time what I really want to know is \"I am not up to date and\nshould merge or rebase.\" Automatically showing _which_ commits diverge\nis a convenience that makes sense if there are a handful of them. For\nlarger cases, the user can easily run \"git log upstream...branch\".\n\nOf course this is speculation and gut feeling; I'll try running with\nthis for a few weeks and see if my opinion changes.\n\n-Peff\n\n\n> \n> We could enhance this with an option that tells the command to\n> check if there is no local change, and automatically fast\n> forward when you are truly behind.  But I ripped out that change\n> because I was unsure what the right way should be to allow users\n> to control it (issues include that checkout should not become\n> automatically interactive).\n> \n> This is hot off the press and I know it tends to be a bit too\n> loud.  It is based on Daniel's \"git checkout in C\" with Dscho's\n> lock_file fix.\n> \n> ---\n> \n>  builtin-checkout.c |  136 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  1 files changed, 136 insertions(+), 0 deletions(-)\n> \n> diff --git a/builtin-checkout.c b/builtin-checkout.c\n> index 59a0ef4..9370ba0 100644\n> --- a/builtin-checkout.c\n> +++ b/builtin-checkout.c\n> @@ -12,6 +12,7 @@\n>  #include \"branch.h\"\n>  #include \"diff.h\"\n>  #include \"revision.h\"\n> +#include \"remote.h\"\n>  \n>  static const char * const checkout_usage[] = {\n>  \t\"git checkout [options] <branch>\",\n> @@ -290,6 +291,139 @@ static int merge_working_tree(struct checkout_opts *opts,\n>  \treturn 0;\n>  }\n>  \n> +/*\n> + * We really should allow cb_data... Yuck\n> + */\n> +static const char *branch_name;\n> +static int branch_name_len;\n> +static char *found_remote;\n> +static char *found_merge;\n> +static int read_branch_config(const char *var, const char *value)\n> +{\n> +\tconst char *name;\n> +\tif (prefixcmp(var, \"branch.\"))\n> +\t\treturn 0; /* not ours */\n> +\tname = var + strlen(\"branch.\");\n> +\tif (strncmp(name, branch_name, branch_name_len) ||\n> +\t    name[branch_name_len] != '.')\n> +\t\treturn 0; /* not ours either */\n> +\tif (!strcmp(name + branch_name_len, \".remote\")) {\n> +\t\t/*\n> +\t\t * Yeah, I know Christian's clean-up should\n> +\t\t * be used here, but the topic is based on an\n> +\t\t * older fork point.\n> +\t\t */\n> +\t\tif (!value)\n> +\t\t\treturn error(\"'%s' not string\", var);\n> +\t\tfound_remote = xstrdup(value);\n> +\t\treturn 0;\n> +\t}\n> +\tif (!strcmp(name + branch_name_len, \".merge\")) {\n> +\t\tif (!value)\n> +\t\t\treturn error(\"'%s' not string\", var);\n> +\t\tfound_merge = xstrdup(value);\n> +\t\treturn 0;\n> +\t}\n> +\treturn 0; /* not ours */\n> +}\n> +\n> +static int find_build_base(const char *ours, char **base)\n> +{\n> +\tstruct remote *remote;\n> +\tstruct refspec spec;\n> +\n> +\t*base = NULL;\n> +\n> +\tbranch_name = ours + strlen(\"refs/heads/\");\n> +\tbranch_name_len = strlen(branch_name);\n> +\tfound_remote = NULL;\n> +\tfound_merge = NULL;\n> +\tgit_config(read_branch_config);\n> +\n> +\tif (!found_remote || !found_merge) {\n> +\tcleanup:\n> +\t\tfree(found_remote);\n> +\t\tfree(found_merge);\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tremote = remote_get(found_remote);\n> +\tmemset(&spec, 0, sizeof(spec));\n> +\tspec.src = found_merge;\n> +\tif (remote_find_tracking(remote, &spec))\n> +\t\tgoto cleanup;\n> +\t*base = spec.dst;\n> +\treturn 1;\n> +}\n> +\n> +static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)\n> +{\n> +\t/*\n> +\t * We have switched to a new branch; is it building on\n> +\t * top of another branch, and if so does that other branch\n> +\t * have changes we do not have yet?\n> +\t */\n> +\tchar *base;\n> +\tunsigned char sha1[20];\n> +\tstruct commit *ours, *theirs;\n> +\tconst char *msgfmt;\n> +\tchar symmetric[84];\n> +\tint show_log;\n> +\n> +\tif (!resolve_ref(new->path, sha1, 1, NULL))\n> +\t\treturn;\n> +\tours = lookup_commit(sha1);\n> +\n> +\tif (!find_build_base(new->path, &base))\n> +\t\treturn;\n> +\n> +\tsprintf(symmetric, \"%s\", sha1_to_hex(sha1));\n> +\n> +\t/*\n> +\t * Ok, it is tracking base; is it ahead of us?\n> +\t */\n> +\tif (!resolve_ref(base, sha1, 1, NULL))\n> +\t\treturn;\n> +\ttheirs = lookup_commit(sha1);\n> +\n> +\tsprintf(symmetric + 40, \"...%s\", sha1_to_hex(sha1));\n> +\n> +\tif (!hashcmp(sha1, ours->object.sha1))\n> +\t\treturn; /* we are the same */\n> +\n> +\tshow_log = 1;\n> +\tif (in_merge_bases(theirs, &ours, 1)) {\n> +\t\tmsgfmt = \"You are ahead of the tracked branch '%s'\\n\";\n> +\t\tshow_log = 0;\n> +\t}\n> +\telse if (in_merge_bases(ours, &theirs, 1))\n> +\t\tmsgfmt = \"Your branch can be fast-forwarded to the tracked branch '%s'\\n\";\n> +\telse\n> +\t\tmsgfmt = \"Both your branch and the tracked branch '%s' have own changes, you would eventually need to merge\\n\";\n> +\n> +\tif (!prefixcmp(base, \"refs/remotes/\"))\n> +\t\tbase += strlen(\"refs/remotes/\");\n> +\tfprintf(stderr, msgfmt, base);\n> +\n> +\tif (show_log) {\n> +\t\tconst char *args[32];\n> +\t\tint ac;\n> +\n> +\t\tac = 0;\n> +\t\targs[ac++] = \"log\";\n> +\t\targs[ac++] = \"--pretty=oneline\";\n> +\t\targs[ac++] = \"--abbrev-commit\";\n> +\t\targs[ac++] = \"--left-right\";\n> +\t\targs[ac++] = \"--boundary\";\n> +\t\targs[ac++] = symmetric;\n> +\t\targs[ac++] = \"--\";\n> +\t\targs[ac] = NULL;\n> +\n> +\t\trun_command_v_opt(args, RUN_GIT_CMD);\n> +\t}\n> +}\n> +\n> +\n>  static void update_refs_for_switch(struct checkout_opts *opts,\n>  \t\t\t\t   struct branch_info *old,\n>  \t\t\t\t   struct branch_info *new)\n> @@ -332,6 +466,8 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n>  \t}\n>  \tremove_branch_state();\n>  \tstrbuf_release(&msg);\n> +\tif (new->path)\n> +\t\tadjust_to_tracking(new, opts);\n>  }\n>  \n>  static int switch_branches(struct checkout_opts *opts,\n"},{"id":"68997","messageId":"alpine.LNX.1.00.0802171146220.5496@iabervon.org","threadId":"11961","inReplyTo":"7vy79k2fus.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-02-17T17:36:43Z","receivedAt":"2008-02-17T17:36:43Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 16 Feb 2008, Junio C Hamano wrote:\n\n> Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> > I'm also in part worried about the lack of publicity \"struct branch\" has \n> > gotten; it would have saved you having to write 64 of 136 lines, so it's \n> > worth you knowing about.\n> \n> Actually, I initially took a look at branch.h and tried to reuse\n> find_tracked_branch() but then realized it was a wrong interface.\n\nYeah, that's the other direction, and for setting it up (so the \nconfiguration isn't there yet, and it's trying to figure out what the \nrequested default is).\n\n> The \"struct branch\" in remote.h (Heh) looks like the right\n> interface.\n\nNow that branch.h exists, it probably should have struct branch, I guess. \nBack when I made struct branch, it was just about finding the right \nconfiguration for fetch, so I was thinking more about the \"doing the right \nthing with remotes\" aspect than the \"configuration about branches\" aspect. \nThey're somewhat intertwined, in any case, because remote_get(NULL) uses \nthe branch configuration to find the default, and branch_get() uses the \nremote configuration to interpret merge settings.\n\n> Documentation/technical/api-*.txt should really talk about\n> what's in remote.c.\n\nAh, that's where that should go. I remember reading about it while I was \non vacation and promptly forgetting all about it. Writing stuff up now.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"69295","messageId":"46a038f90802190903g1a19e38i30198b368a800a89@mail.gmail.com","threadId":"11961","inReplyTo":"7vfxvs75kp.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2008-02-19T17:03:01Z","receivedAt":"2008-02-19T17:03:01Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Feb 17, 2008 2:08 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > Perhaps making \"git-checkout\" to notice this and offer (or\n> > suggest) fast-forwarding at that point may be safer and make\n> > more sense.  You cannot grow your local branch unless you check\n> > them out, and your remote tracking will keep growing without the\n> > auto-ff you are suggesting, so it is not like people will lose\n> > anchoring point to compare between branches if we do not\n> > auto-ff.\n>\n> So I did this.\n\nGreat - *thanks*. I'm travelling ATM so lousy connectivity and\nshattered focus. I did a fetch of git.git and can't spot this in next,\npu or master. Reading further down the thread I see that you're\nprobably rewriting it to use tree struct. Will give your initial patch\na whirl anyway.\n\ncheers,\n\n\nmartin\n"},{"id":"69362","messageId":"7vzltwavf9.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802101303140.11591@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-20T08:23:06Z","receivedAt":"2008-02-20T08:23:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Hmm.  So that means that if an old-timer comes to help to a new-comer, \n> the old-timer will be surprised?\n\nActually, after carefully examining what I have been doing, I\nthink this \"somebody cries 'git push ;# nothing else' does not\nwork, and old timer needs to remember to check one extra thing\nto help\" has been a bit overblown.\n\nTo diagnose \"git push ;# nothing else\", you would already need\nto ask the following _anyway_:\n\n - On what branch are you?\n\n - Do you have \"branch.$current_branch.remote\"?\n\n - What is \"branch.$current_branch.remote\" set to?\n\n - Do you have remote.$that_remote.url?\n\n   - If it is http://, do you have very new version of curl\n     library, often not even in distro?\n\n   - If it is http://, does it end with '/'?\n\n   - If it is http://, do you have DAV enabled over there?\n\n   - If it is host:path, does your non-interactive ssh get\n     appropriate PATH at the other end?\n\n   - Is your username there the same as local?  Otherwise do you\n     have \"User your_name_over_there\" set up in your\n     $HOME/.ssh/config?\n\n   - 47 other questions about transfers.\n\n - Do you have remote.$that_remote.push?\n\n - What local branches do you have?\n\n - What local branches does $that_remote have?\n\nSo it is not _so_ unreasonable if we add an extra configuration\nor two to this mix.\n\nWhat configuration semantics is reasonable is a different\nmatter.  Let's back up a bit.\n\nThe \"matching\" semantics has been advertised as a convenient way\nto keep track of which branches you would want publish and which\nones to keep private without having to have extra configuration.\nThis is very true for people whose workflow is based on _owned_\npublic distribution points.  The destination is controlled by\nyou and you alone, and after pushing the branches you want to\nshow out explicitly, the destination repository _remembers_\nwhich branches you are interested in publishing for later\n\"matching\" pushes.  When you are no longer interested in showing\nthat work, you remove it from the remote and matching and that\n(1) stops publishing and at the same time (2) remembers you are\nno longer interested in publishing.\n\nHowever, when you allow others to push into the destination, the\nset of branches there obviously cannot serve as your private\nconfiguration anymore.  So \"matching\" can never be a convenient\nway if your push is to a shared repository.\n\nWhich would mean that \"matching\" is not a personal taste nor\neven per-repository matter.  I think it is reasonable to set\nthis per-remote.\n\n    You may have a repository you use during daytime on your\n    desktop, and the repository may have more than one remotes\n    defined.  \"origin\" may point to a shared repository you push to\n    and fetch from in order to work together with others, \"backup\"\n    may point to another repository on your server you push your\n    work into, and \"satellite\" may point to yet another repository\n    on your notebook when you are done for the day and take your WIP\n    along with you.\n\n    You may not want \"matching\" when interacting with the shared\n    repository (if you always want \"current only\" is a different\n    matter, but let's pretend you do), but you would want\n    \"matching\" when pushing back to \"satellite\", and you would\n    want \"mirror\" when pushing to \"backup\".\n\nSo perhaps we can have \"remote.*.push\" that says \"current\" in\nsome way.  Tentatively let's say the syntax is like this:\n\n\t[remote \"origin\"]\n        \turl = server.oss.example.org:/pub/project.git/\n                push = HEAD\n                fetch = +refs/heads/*:refs/remotes/origin/*\n\t[remote \"backup\"]\n        \turl = server.example.com:/home/me/mine.git/\n                push = +refs/*:refs/*\n\t[remote \"satellite\"]\n        \turl = notebook.example.com:/home/me/mine.git/\n\n\t[branch \"master\"]\n        \tremote = \"origin\"\n                merge = refs/heads/master\n\t[branch \"ticket-47\"]\n               \tremote = \"origin\"\n                merge = refs/heads/ticket-47\n\nWhile on \"master\", \"git push\" will say...\n\n\tAh, you are too lazy to say where to push to.\n\tbranch.master.remote says \"origin\", so that is it.\n\n\tAnd you are too lazy to say what to push either.\n\tremote.origin.push says HEAD which is a special token\n\tthat means the current branch.\n\n\tLet's pretend you told me \"git push origin master\"\n\nI was hoping we can do without the \"remote.*.push = HEAD\" if we\ncan detect the remote is a shared repository while talking to\nit, but I think it is a bit too much magic, because we cannot\nvisualize what the pushing side and the receiving side  are\nnegotiating.\n\nPutting this \"push = HEAD\" by default when \"git clone\" and \"git\nremote add\" creates the [remote \"$remote\"] section is probably\npossible, and at that stage we may even be able to do the \"if\nthe other end is shared, then set this up automagically\", as the\nresult of the magic can be inspected in the resulting config\nfile.\n"},{"id":"69369","messageId":"alpine.LSU.1.00.0802201305350.17164@racer.site","threadId":"11961","inReplyTo":"7vzltwavf9.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-20T13:06:59Z","receivedAt":"2008-02-20T13:06:59Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 20 Feb 2008, Junio C Hamano wrote:\n\n> Putting this \"push = HEAD\" by default when \"git clone\" and \"git remote \n> add\" creates the [remote \"$remote\"] section is probably possible, and at \n> that stage we may even be able to do the \"if the other end is shared, \n> then set this up automagically\", as the result of the magic can be \n> inspected in the resulting config file.\n\nI think this is too magic, both of it.  Once people get used to \"git push\" \nbeing implicitly \"git push origin HEAD\", why should they not expect \"git \npush <somewhere-else>\" to push \"HEAD\" implicitly, too?\n\nCiao,\nDscho\n"},{"id":"69371","messageId":"20080220140306.GA6928@sigill.intra.peff.net","threadId":"11961","inReplyTo":"7vzltwavf9.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-20T14:03:07Z","receivedAt":"2008-02-20T14:03:07Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 20, 2008 at 12:23:06AM -0800, Junio C Hamano wrote:\n\n> [long description of shared repository workflow]\n> So perhaps we can have \"remote.*.push\" that says \"current\" in\n> some way.  Tentatively let's say the syntax is like this:\n\nI think everything you said here makes perfect sense; changing the push\nrefspec to say \"push the current\" for a particular remote is much more\nsensible than an overall default. In fact, I half-expected this to\njust work without a patch, since \"git push origin HEAD\" already works.\nHowever, we don't treat command line refspecs and config refspecs the\nsame way, which IMHO is a needless inconsistency. How about this:\n\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 9f727c0..ca90150 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -68,8 +68,7 @@ static int do_push(const char *repo, int flags)\n \tif (!refspec\n \t\t&& !(flags & TRANSPORT_PUSH_ALL)\n \t\t&& remote->push_refspec_nr) {\n-\t\trefspec = remote->push_refspec;\n-\t\trefspec_nr = remote->push_refspec_nr;\n+\t\tset_refspecs(remote->push_refspec, remote->push_refspec_nr);\n \t}\n \terrs = 0;\n \tfor (i = 0; i < remote->url_nr; i++) {\n\nAt which point this now works as you described:\n\n  git config remote.origin.push HEAD\n\n> I was hoping we can do without the \"remote.*.push = HEAD\" if we\n> can detect the remote is a shared repository while talking to\n> it, but I think it is a bit too much magic, because we cannot\n> visualize what the pushing side and the receiving side  are\n> negotiating.\n\nHow are you detecting that the remote is a shared repository? By the\ncore.sharedrepository config option? I use several shared repositories,\nand I never set that variable; instead I use filesystem ACLs (which we\ncould at least detect). It is my understanding that some people even\nhave repositories where multiple users share the same filesystem uid but\nconnect with different ssh keys.  I don't think that is even detectable.\n\n-Peff\n"},{"id":"69375","messageId":"76718490802200720w4dd89dc1lf7b19d546d3bfd00@mail.gmail.com","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802201305350.17164@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2008-02-20T15:20:01Z","receivedAt":"2008-02-20T15:20:01Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Feb 20, 2008 8:06 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Wed, 20 Feb 2008, Junio C Hamano wrote:\n>\n> > Putting this \"push = HEAD\" by default when \"git clone\" and \"git remote\n> > add\" creates the [remote \"$remote\"] section is probably possible, and at\n> > that stage we may even be able to do the \"if the other end is shared,\n> > then set this up automagically\", as the result of the magic can be\n> > inspected in the resulting config file.\n>\n> I think this is too magic, both of it.  Once people get used to \"git push\"\n> being implicitly \"git push origin HEAD\", why should they not expect \"git\n> push <somewhere-else>\" to push \"HEAD\" implicitly, too?\n\nWell then, how about (don't cringe too much now...)\n\n  push.conservative = true\n\nIf enabled and \"git push\" is run w/o arguments, it will first emit what\nit plans to push and then prompt with \"yes/no.\" I'm kinda opposed to\nsilly prompts -- folks just always go right past them -- so I dunno.\n\nBut it does make the operation a bit more safe I guess.\n\nj.\n"},{"id":"69377","messageId":"alpine.LSU.1.00.0802201535250.17164@racer.site","threadId":"11961","inReplyTo":"76718490802200720w4dd89dc1lf7b19d546d3bfd00@mail.gmail.com","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-20T15:38:31Z","receivedAt":"2008-02-20T15:38:31Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 20 Feb 2008, Jay Soffian wrote:\n\n> On Feb 20, 2008 8:06 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> >\n> > On Wed, 20 Feb 2008, Junio C Hamano wrote:\n> >\n> > > Putting this \"push = HEAD\" by default when \"git clone\" and \"git \n> > > remote add\" creates the [remote \"$remote\"] section is probably \n> > > possible, and at that stage we may even be able to do the \"if the \n> > > other end is shared, then set this up automagically\", as the result \n> > > of the magic can be inspected in the resulting config file.\n> >\n> > I think this is too magic, both of it.  Once people get used to \"git \n> > push\" being implicitly \"git push origin HEAD\", why should they not \n> > expect \"git push <somewhere-else>\" to push \"HEAD\" implicitly, too?\n> \n> Well then, how about (don't cringe too much now...)\n> \n>   push.conservative = true\n> \n> If enabled and \"git push\" is run w/o arguments, it will first emit what \n> it plans to push and then prompt with \"yes/no.\" I'm kinda opposed to \n> silly prompts -- folks just always go right past them -- so I dunno.\n> \n> But it does make the operation a bit more safe I guess.\n\nThat depends awfully on your definition of \"safe\".\n\nI, for one, hate the idea already, that I am \"safe\" when \"git push\" does \nnot do the thing I asked it to, and which it has done for a couple of \nyears now without complaint, and which I have gotten used to.\n\nAnd then, there will be a great confusion for me, since I work on 5 \ndifferent machines on an average day, with 5 different git versions, and \nhaving different config settings.\n\nThat is not \"safe\" for me.\n\nThankyouverymuch,\nDscho\n"},{"id":"69379","messageId":"8aa486160802200801p28b74755xd1242a74c0e417a8@mail.gmail.com","threadId":"11961","inReplyTo":"20080217122815.GA26031@sigill.intra.peff.net","subject":"Re: [RFC] checkout to notice forks (Re: Minor annoyance with git push)","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2008-02-20T16:01:15Z","receivedAt":"2008-02-20T16:01:15Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Sun, Feb 17, 2008 at 1:28 PM, Jeff King <peff@peff.net> wrote:\n> On Sat, Feb 16, 2008 at 05:08:22PM -0800, Junio C Hamano wrote:\n>\n>  > and you say \"git checkout next\", then after we switch the branch\n>  > we check the upstream (in this case, refs/remotes/linus/next)\n>  > and our branch, and:\n>  >\n>  >     (1) if they match, nothing happens;\n>  >\n>  >     (2) if you are ahead (i.e. the upstream is a strict ancestor\n>  >         of you), one line message tells you so;\n>  >\n>  >     (3) otherwise, you are either behind or you and the upstream\n>  >         have forked.  One line message will tell you which and\n>  >         then you will see a \"log --pretty=oneline --left-right\".\n>\n>  Overall I think this is a sensible idea. For (3), it probably makes\n>  sense to limit the output in some cases. If I checkout a topic branch\n>  that I haven't looked at in a few days or even weeks, I am going to get\n>  spammed with hundreds of commits.\n>\n>  Most of the time what I really want to know is \"I am not up to date and\n>  should merge or rebase.\" Automatically showing _which_ commits diverge\n>  is a convenience that makes sense if there are a handful of them. For\n>  larger cases, the user can easily run \"git log upstream...branch\".\n\nI prefer to always have a summary as:\n\nThe tracking branch is ahead:\n $branchsha1..$upstreamsha1 (<n> commits)\n\nand\n\nBranch and tracking branch have diverged:\n $branchsha1...$upstreamsha1 (<n>|<m> commits)\n\nor something like that.\n\nAdditionally, the text send to stderr (Switched to... Your branch can\nbe fast...) is hidden when the pager run.\n\nSanti\n"},{"id":"69383","messageId":"7vk5kz7btw.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"20080220140306.GA6928@sigill.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-20T17:54:35Z","receivedAt":"2008-02-20T17:54:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> ... In fact, I half-expected this to\n> just work without a patch, since \"git push origin HEAD\" already works.\n> However, we don't treat command line refspecs and config refspecs the\n> same way, which IMHO is a needless inconsistency. How about this:\n>\n> diff --git a/builtin-push.c b/builtin-push.c\n> index 9f727c0..ca90150 100644\n> --- a/builtin-push.c\n> +++ b/builtin-push.c\n> @@ -68,8 +68,7 @@ static int do_push(const char *repo, int flags)\n>  \tif (!refspec\n>  \t\t&& !(flags & TRANSPORT_PUSH_ALL)\n>  \t\t&& remote->push_refspec_nr) {\n> -\t\trefspec = remote->push_refspec;\n> -\t\trefspec_nr = remote->push_refspec_nr;\n> +\t\tset_refspecs(remote->push_refspec, remote->push_refspec_nr);\n>  \t}\n>  \terrs = 0;\n>  \tfor (i = 0; i < remote->url_nr; i++) {\n\nYeah, we are on the same page.  See the patch I sent out last night ;-)\n\n> At which point this now works as you described:\n>\n>   git config remote.origin.push HEAD\n\nExactly.\n\n>> I was hoping we can do without the \"remote.*.push = HEAD\" if we\n>> can detect the remote is a shared repository while talking to\n>> it, but I think it is a bit too much magic, because we cannot\n>> visualize what the pushing side and the receiving side  are\n>> negotiating.\n>\n> How are you detecting that the remote is a shared repository?\n\nI am not.  I only said \"... may even be able to\" ;-).\n\nThe autodetection is not even the first step to tackle this\nissue anyway.  The \"HEAD\" magic (or if somebody comes up with a\nbetter design, that one) comes first, deciding if such an\nautodetection is even a good idea comes next, and then iff we\ndecide that it is a good idea finally comes the task of finding\nout how we do so.\n\nI'd presume that the upload-pack side can internally check \"int\nshared_repository\" and the protocol extension that conveys that\ninformation to the other end is easy enough.  As always, dumb\ntransports are second class citizens and need their own hacks.\n\n> By the core.sharedrepository config option? I use several\n> shared repositories, and I never set that variable; instead\n> ...\n\nIt is _your_ problem that you do not use published interface,\nisn't it?\n"},{"id":"69385","messageId":"20080220181513.GA16289@sigill.intra.peff.net","threadId":"11961","inReplyTo":"7vk5kz7btw.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-20T18:15:14Z","receivedAt":"2008-02-20T18:15:14Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 20, 2008 at 09:54:35AM -0800, Junio C Hamano wrote:\n\n> > +++ b/builtin-push.c\n> > @@ -68,8 +68,7 @@ static int do_push(const char *repo, int flags)\n> >  \tif (!refspec\n> >  \t\t&& !(flags & TRANSPORT_PUSH_ALL)\n> >  \t\t&& remote->push_refspec_nr) {\n> > -\t\trefspec = remote->push_refspec;\n> > -\t\trefspec_nr = remote->push_refspec_nr;\n> > +\t\tset_refspecs(remote->push_refspec, remote->push_refspec_nr);\n> >  \t}\n> >  \terrs = 0;\n> >  \tfor (i = 0; i < remote->url_nr; i++) {\n> \n> Yeah, we are on the same page.  See the patch I sent out last night ;-)\n\nMeaning you will take this patch? (And yes, I think the \"+HEAD\" patch\nyou sent is a good fix, regardless of everything else we've talked\nabout).\n\n> > How are you detecting that the remote is a shared repository?\n> \n> I am not.  I only said \"... may even be able to\" ;-).\n> \n> The autodetection is not even the first step to tackle this\n> issue anyway.  The \"HEAD\" magic (or if somebody comes up with a\n> better design, that one) comes first, deciding if such an\n> autodetection is even a good idea comes next, and then iff we\n> decide that it is a good idea finally comes the task of finding\n> out how we do so.\n\nDidn't the \"HEAD\" magic just come? :) Is there some part of that that\nyou are unhappy with?\n\n> I'd presume that the upload-pack side can internally check \"int\n> shared_repository\" and the protocol extension that conveys that\n> information to the other end is easy enough.  As always, dumb\n> transports are second class citizens and need their own hacks.\n\nReasonable.\n\n> > By the core.sharedrepository config option? I use several\n> > shared repositories, and I never set that variable; instead\n> > ...\n> \n> It is _your_ problem that you do not use published interface,\n> isn't it?\n\nI would agree with you if core.sharedRepository had ever been introduced\nas a signal flag for a particular workflow, and not simply as a way to\nset up the umask.\n\nIf you want to introduce those semantics to sharedRepository, that is\nnot unreasonable, but:\n\n  - recognize that you don't automagically turn on this feature for\n    repositories using the shared workflow, since they may or may not\n    even have this flag enabled\n\n  - recognize that people who _do_ want this new behavior might not want\n    the umask side effects (and in fact, those side effects can reduce\n    security if the users are in a group with untrusted users)\n\nso I think that a new config option is probably safer, and not\nnecessarily less likely to work automatically.\n\nThat being said, I think this sort of automatic detection should wait at\nleast one release cycle. Once the behavior is configurable at all, we\ncan see how people adopt it into their workflows and if there is really\nany desire for detection at all.\n\n-Peff\n"},{"id":"69387","messageId":"20080220181756.GB16289@sigill.intra.peff.net","threadId":"11961","inReplyTo":"20080220181513.GA16289@sigill.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-20T18:17:56Z","receivedAt":"2008-02-20T18:17:56Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 20, 2008 at 01:15:14PM -0500, Jeff King wrote:\n\n> > Yeah, we are on the same page.  See the patch I sent out last night ;-)\n> \n> Meaning you will take this patch? (And yes, I think the \"+HEAD\" patch\n> you sent is a good fix, regardless of everything else we've talked\n> about).\n\nNevermind this question if you are going to take Daniel's patch to move\nthe ref resolution to the lower layer.\n\n-Peff\n"},{"id":"69388","messageId":"7vskzn5w3m.fsf@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"20080220181513.GA16289@sigill.intra.peff.net","subject":"Re: Minor annoyance with git push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-20T18:19:41Z","receivedAt":"2008-02-20T18:19:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Meaning you will take this patch? (And yes, I think the \"+HEAD\" patch\n> you sent is a good fix, regardless of everything else we've talked\n> about).\n\nYes I would, except that I think Daniel's is much better and is\nto the point.  Doesn't it cover all the issues we discussed so\nfar?\n\n> ... Once the behavior is configurable at all, we\n> can see how people adopt it into their workflows and if there is really\n> any desire for detection at all.\n\nYup.\n"},{"id":"69389","messageId":"20080220182315.GA16485@sigill.intra.peff.net","threadId":"11961","inReplyTo":"7vskzn5w3m.fsf@gitster.siamese.dyndns.org","subject":"Re: Minor annoyance with git push","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-20T18:23:15Z","receivedAt":"2008-02-20T18:23:15Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 20, 2008 at 10:19:41AM -0800, Junio C Hamano wrote:\n\n> Yes I would, except that I think Daniel's is much better and is\n> to the point.  Doesn't it cover all the issues we discussed so\n> far?\n\nYes, I like Daniel's patch (it came right after I wrote my response).\n\n-Peff\n"},{"id":"69420","messageId":"7vy79f2pqk.fsf_-_@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"46a038f90802190903g1a19e38i30198b368a800a89@mail.gmail.com","subject":"[PATCH] checkout: tone down the \"forked status\" diagnostic messages","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-20T23:05:23Z","receivedAt":"2008-02-20T23:05:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When checking out a branch that is behind or forked from a\nbranch you are building on top of, we used to show full\nleft-right log but if you already _know_ you have long history\nsince you forked, it is a bit too much.\n\nThis tones down the message quite a bit, by only showing the\nnumber of commits each side has since they diverged.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This obviously comes on top of the earlier patch of mine,\n   which in turn is on top of Daniel's \"checkout written in C\".\n\n builtin-checkout.c |  102 ++++++++++++++++++++++++++++++++--------------------\n 1 files changed, 63 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 5291f72..261f67f 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -301,64 +301,88 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n \tchar *base;\n \tunsigned char sha1[20];\n \tstruct commit *ours, *theirs;\n-\tconst char *msgfmt;\n \tchar symmetric[84];\n-\tint show_log;\n+\tstruct rev_info revs;\n+\tconst char *rev_argv[10];\n+\tint rev_argc;\n+\tint num_ours, num_theirs;\n+\tconst char *remote_msg;\n \tstruct branch *branch = branch_get(NULL);\n \n+\t/*\n+\t * Nothing to report unless we are marked to build on top of\n+\t * somebody else.\n+\t */\n \tif (!branch || !branch->merge)\n \t\treturn;\n \n-\tbase = branch->merge[0]->dst;\n-\n-\tours = new->commit;\n-\n-\tsprintf(symmetric, \"%s\", sha1_to_hex(ours->object.sha1));\n-\n \t/*\n-\t * Ok, it is tracking base; is it ahead of us?\n+\t * If what we used to build on no longer exists, there is\n+\t * nothing to report.\n \t */\n+\tbase = branch->merge[0]->dst;\n \tif (!resolve_ref(base, sha1, 1, NULL))\n \t\treturn;\n-\ttheirs = lookup_commit(sha1);\n-\n-\tsprintf(symmetric + 40, \"...%s\", sha1_to_hex(sha1));\n \n+\ttheirs = lookup_commit(sha1);\n+\tours = new->commit;\n \tif (!hashcmp(sha1, ours->object.sha1))\n \t\treturn; /* we are the same */\n \n-\tshow_log = 1;\n-\tif (in_merge_bases(theirs, &ours, 1)) {\n-\t\tmsgfmt = \"You are ahead of the tracked branch '%s'\\n\";\n-\t\tshow_log = 0;\n+\t/* Run \"rev-list --left-right ours...theirs\" internally... */\n+\trev_argc = 0;\n+\trev_argv[rev_argc++] = NULL;\n+\trev_argv[rev_argc++] = \"--left-right\";\n+\trev_argv[rev_argc++] = symmetric;\n+\trev_argv[rev_argc++] = \"--\";\n+\trev_argv[rev_argc] = NULL;\n+\n+\tstrcpy(symmetric, sha1_to_hex(ours->object.sha1));\n+\tstrcpy(symmetric + 40, \"...\");\n+\tstrcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));\n+\n+\tinit_revisions(&revs, NULL);\n+\tsetup_revisions(rev_argc, rev_argv, &revs, NULL);\n+\tprepare_revision_walk(&revs);\n+\n+\t/* ... and count the commits on each side. */\n+\tnum_ours = 0;\n+\tnum_theirs = 0;\n+\twhile (1) {\n+\t\tstruct commit *c = get_revision(&revs);\n+\t\tif (!c)\n+\t\t\tbreak;\n+\t\tif (c->object.flags & SYMMETRIC_LEFT)\n+\t\t\tnum_ours++;\n+\t\telse\n+\t\t\tnum_theirs++;\n \t}\n-\telse if (in_merge_bases(ours, &theirs, 1))\n-\t\tmsgfmt = \"Your branch can be fast-forwarded to the tracked branch '%s'\\n\";\n-\telse\n-\t\tmsgfmt = \"Both your branch and the tracked branch '%s' have own changes, you would eventually need to merge\\n\";\n \n-\tif (!prefixcmp(base, \"refs/remotes/\"))\n+\tif (!prefixcmp(base, \"refs/remotes/\")) {\n+\t\tremote_msg = \" remote\";\n \t\tbase += strlen(\"refs/remotes/\");\n-\tfprintf(stderr, msgfmt, base);\n-\n-\tif (show_log) {\n-\t\tconst char *args[32];\n-\t\tint ac;\n-\n-\t\tac = 0;\n-\t\targs[ac++] = \"log\";\n-\t\targs[ac++] = \"--pretty=oneline\";\n-\t\targs[ac++] = \"--abbrev-commit\";\n-\t\targs[ac++] = \"--left-right\";\n-\t\targs[ac++] = \"--boundary\";\n-\t\targs[ac++] = symmetric;\n-\t\targs[ac++] = \"--\";\n-\t\targs[ac] = NULL;\n-\n-\t\trun_command_v_opt(args, RUN_GIT_CMD);\n+\t} else {\n+\t\tremote_msg = \"\";\n \t}\n-}\n \n+\tif (!num_theirs)\n+\t\tprintf(\"Your branch is ahead of the tracked%s branch '%s' \"\n+\t\t       \"by %d commit%s.\\n\",\n+\t\t       remote_msg, base,\n+\t\t       num_ours, (num_ours == 1) ? \"\" : \"s\");\n+\telse if (!num_ours)\n+\t\tprintf(\"Your branch is behind of the tracked%s branch '%s' \"\n+\t\t       \"by %d commit%s,\\n\"\n+\t\t       \"and can be fast-forwarded.\\n\",\n+\t\t       remote_msg, base,\n+\t\t       num_theirs, (num_theirs == 1) ? \"\" : \"s\");\n+\telse\n+\t\tprintf(\"Your branch and the tracked%s branch '%s' \"\n+\t\t       \"have diverged,\\nand respectively \"\n+\t\t       \"have %d and %d different commit(s) each.\\n\",\n+\t\t       remote_msg, base,\n+\t\t       num_ours, num_theirs);\n+}\n \n static void update_refs_for_switch(struct checkout_opts *opts,\n \t\t\t\t   struct branch_info *old,\n"},{"id":"69442","messageId":"20080221014513.GA7185@coredump.intra.peff.net","threadId":"11961","inReplyTo":"7vy79f2pqk.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [PATCH] checkout: tone down the \"forked status\" diagnostic messages","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-21T01:45:13Z","receivedAt":"2008-02-21T01:45:13Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 20, 2008 at 03:05:23PM -0800, Junio C Hamano wrote:\n\n> @@ -301,64 +301,88 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n>  \tchar *base;\n>  \tunsigned char sha1[20];\n>  \tstruct commit *ours, *theirs;\n> -\tconst char *msgfmt;\n>  \tchar symmetric[84];\n> -\tint show_log;\n> +\tstruct rev_info revs;\n> +\tconst char *rev_argv[10];\n> +\tint rev_argc;\n> +\tint num_ours, num_theirs;\n> +\tconst char *remote_msg;\n>  \tstruct branch *branch = branch_get(NULL);\n\nShouldn't this be branch_get(new->name)? branch_get calls read_config(),\nwhich caches the \"current branch\" information, so it's possible to end\nup with stale branch info. Try:\n\n  git clone git://git.kernel.org/pub/scm/git/git.git\n  git checkout -b next origin/next\n\nI get:\n\n  Branch next set up to track remote branch refs/remotes/origin/next.\n  Switched to a new branch \"next\"\n  Your branch is ahead of the tracked remote branch 'origin/master' by 76\n  commits.\n\nSwitching to master and then back to the already-created \"next\" works\nfine.\n\nEven safer, I think, would be a way to invalidate the information cached\nin read_config when we change branches; this would fix it for any other\ncallsites that look at the current branch from the same git invocation\nthat changes the current branch.\n\n> +\tif (!num_theirs)\n> +\t\tprintf(\"Your branch is ahead of the tracked%s branch '%s' \"\n> +\t\t       \"by %d commit%s.\\n\",\n> +\t\t       remote_msg, base,\n> +\t\t       num_ours, (num_ours == 1) ? \"\" : \"s\");\n> +\telse if (!num_ours)\n> +\t\tprintf(\"Your branch is behind of the tracked%s branch '%s' \"\n> +\t\t       \"by %d commit%s,\\n\"\n> +\t\t       \"and can be fast-forwarded.\\n\",\n\nWhile not uncommon colloquially, \"behind of\" is not grammatically\ncorrect. \"behind\" is a preposition, so the \"of\" is redundant (it is\nnecessary in the top string because \"ahead\" is an adverb).\n\n-Peff\n"},{"id":"69445","messageId":"76718490802201856x54f160e7m7bb6ba10fada845e@mail.gmail.com","threadId":"11961","inReplyTo":"7vy79f2pqk.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [PATCH] checkout: tone down the \"forked status\" diagnostic messages","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2008-02-21T02:56:41Z","receivedAt":"2008-02-21T02:56:41Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 20, 2008 at 6:05 PM, Junio C Hamano <gitster@pobox.com> wrote:\n\n>  diff --git a/builtin-checkout.c b/builtin-checkout.c\n>  index 5291f72..261f67f 100644\n>  --- a/builtin-checkout.c\n>  +++ b/builtin-checkout.c\n>  @@ -301,64 +301,88 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n>         char *base;\n>  +       base = branch->merge[0]->dst;\n>         if (!resolve_ref(base, sha1, 1, NULL))\n>                 return;\n\nApparently base can be null, which on OS X causes a Bus Error in resolve_ref\nwhen it calls strcmp(ref, list->name)\n\nj.\n"},{"id":"69446","messageId":"7vk5kzynya.fsf_-_@gitster.siamese.dyndns.org","threadId":"11961","inReplyTo":"20080221014513.GA7185@coredump.intra.peff.net","subject":"[PATCH] checkout: updates to tracking report","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-21T03:42:53Z","receivedAt":"2008-02-21T03:42:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n>>  \tstruct branch *branch = branch_get(NULL);\n>\n> Shouldn't this be branch_get(new->name)?\n\nPerhaps.\n\n> ...\n> While not uncommon colloquially, \"behind of\" is not grammatically\n> correct. \"behind\" is a preposition, so the \"of\" is redundant (it is\n> necessary in the top string because \"ahead\" is an adverb).\n\nThanks.\n\n-- >8 --\n\nAsk branch_get() for the new branch explicitly instead of\nletting it return a potentially stale information.\n\nTighten the logic to find the tracking branch to deal better\nwith misconfigured repositories (i.e. branch.*.merge can exist\nbut it may not have a refspec that fetches to .it)\n\nAlso fixes grammar in a message, as pointed out by Jeff King.\n\nThe function is about reporting and not automatically\nfast-forwarding to the upstream, so stop calling it\n\"adjust-to\".\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-checkout.c |   10 +++++-----\n 1 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex f51b77a..19413eb 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -290,7 +290,7 @@ static int merge_working_tree(struct checkout_opts *opts,\n \treturn 0;\n }\n \n-static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)\n+static void report_tracking(struct branch_info *new, struct checkout_opts *opts)\n {\n \t/*\n \t * We have switched to a new branch; is it building on\n@@ -306,13 +306,13 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n \tint rev_argc;\n \tint num_ours, num_theirs;\n \tconst char *remote_msg;\n-\tstruct branch *branch = branch_get(NULL);\n+\tstruct branch *branch = branch_get(new->name);\n \n \t/*\n \t * Nothing to report unless we are marked to build on top of\n \t * somebody else.\n \t */\n-\tif (!branch || !branch->merge)\n+\tif (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)\n \t\treturn;\n \n \t/*\n@@ -370,7 +370,7 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n \t\t       remote_msg, base,\n \t\t       num_ours, (num_ours == 1) ? \"\" : \"s\");\n \telse if (!num_ours)\n-\t\tprintf(\"Your branch is behind of the tracked%s branch '%s' \"\n+\t\tprintf(\"Your branch is behind the tracked%s branch '%s' \"\n \t\t       \"by %d commit%s,\\n\"\n \t\t       \"and can be fast-forwarded.\\n\",\n \t\t       remote_msg, base,\n@@ -426,7 +426,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n \tremove_branch_state();\n \tstrbuf_release(&msg);\n \tif (!opts->quiet && (new->path || !strcmp(new->name, \"HEAD\")))\n-\t\tadjust_to_tracking(new, opts);\n+\t\treport_tracking(new, opts);\n }\n \n static int switch_branches(struct checkout_opts *opts,\n-- \n1.5.4.2.261.g851a5\n"},{"id":"69454","messageId":"76718490802202127y664cb986u64ab55bbc02fb72e@mail.gmail.com","threadId":"11961","inReplyTo":"7vk5kzynya.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [PATCH] checkout: updates to tracking report","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2008-02-21T05:27:09Z","receivedAt":"2008-02-21T05:27:09Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Feb 20, 2008 at 10:42 PM, Junio C Hamano <gitster@pobox.com> wrote:\n\n>   builtin-checkout.c |   10 +++++-----\n>   1 files changed, 5 insertions(+), 5 deletions(-)\n\nActually, it would be nice to get this information w/o having to\ncheckout each branch. \"git show-branch --tracking-status\" maybe\nto report it for all relevant branches?\n\nj.\n"},{"id":"69493","messageId":"alpine.LNX.1.00.0802211146410.19024@iabervon.org","threadId":"11961","inReplyTo":"7vk5kzynya.fsf_-_@gitster.siamese.dyndns.org","subject":"Re: [PATCH] checkout: updates to tracking report","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-02-21T17:02:01Z","receivedAt":"2008-02-21T17:02:01Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 20 Feb 2008, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> >>  \tstruct branch *branch = branch_get(NULL);\n> >\n> > Shouldn't this be branch_get(new->name)?\n> \n> Perhaps.\n> \n> > ...\n> > While not uncommon colloquially, \"behind of\" is not grammatically\n> > correct. \"behind\" is a preposition, so the \"of\" is redundant (it is\n> > necessary in the top string because \"ahead\" is an adverb).\n> \n> Thanks.\n> \n> -- >8 --\n> \n> Ask branch_get() for the new branch explicitly instead of\n> letting it return a potentially stale information.\n\nI think it would be good to update current_branch in remote.c when we \nchange branches, just on principle, but we also might as well not depend \non that here.\n\n> Tighten the logic to find the tracking branch to deal better\n> with misconfigured repositories (i.e. branch.*.merge can exist\n> but it may not have a refspec that fetches to .it)\n> \n> Also fixes grammar in a message, as pointed out by Jeff King.\n> \n> The function is about reporting and not automatically\n> fast-forwarding to the upstream, so stop calling it\n> \"adjust-to\".\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n\nAcked-by: Daniel Barkalow <barkalow@iabervon.org>\n\n> ---\n>  builtin-checkout.c |   10 +++++-----\n>  1 files changed, 5 insertions(+), 5 deletions(-)\n> \n> diff --git a/builtin-checkout.c b/builtin-checkout.c\n> index f51b77a..19413eb 100644\n> --- a/builtin-checkout.c\n> +++ b/builtin-checkout.c\n> @@ -290,7 +290,7 @@ static int merge_working_tree(struct checkout_opts *opts,\n>  \treturn 0;\n>  }\n>  \n> -static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)\n> +static void report_tracking(struct branch_info *new, struct checkout_opts *opts)\n>  {\n>  \t/*\n>  \t * We have switched to a new branch; is it building on\n> @@ -306,13 +306,13 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n>  \tint rev_argc;\n>  \tint num_ours, num_theirs;\n>  \tconst char *remote_msg;\n> -\tstruct branch *branch = branch_get(NULL);\n> +\tstruct branch *branch = branch_get(new->name);\n>  \n>  \t/*\n>  \t * Nothing to report unless we are marked to build on top of\n>  \t * somebody else.\n>  \t */\n> -\tif (!branch || !branch->merge)\n> +\tif (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)\n\nbranch->merge[i] can't actually be NULL; all of the allocated space in the \narray gets stuff stored in it.\n\n>  \t\treturn;\n>  \n>  \t/*\n> @@ -370,7 +370,7 @@ static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *op\n>  \t\t       remote_msg, base,\n>  \t\t       num_ours, (num_ours == 1) ? \"\" : \"s\");\n>  \telse if (!num_ours)\n> -\t\tprintf(\"Your branch is behind of the tracked%s branch '%s' \"\n> +\t\tprintf(\"Your branch is behind the tracked%s branch '%s' \"\n>  \t\t       \"by %d commit%s,\\n\"\n>  \t\t       \"and can be fast-forwarded.\\n\",\n>  \t\t       remote_msg, base,\n> @@ -426,7 +426,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n>  \tremove_branch_state();\n>  \tstrbuf_release(&msg);\n>  \tif (!opts->quiet && (new->path || !strcmp(new->name, \"HEAD\")))\n> -\t\tadjust_to_tracking(new, opts);\n> +\t\treport_tracking(new, opts);\n>  }\n>  \n>  static int switch_branches(struct checkout_opts *opts,\n> -- \n> 1.5.4.2.261.g851a5\n> \n"},{"id":"69529","messageId":"20080221223549.GA26266@dervierte","threadId":"11961","inReplyTo":"alpine.LSU.1.00.0802201535250.17164@racer.site","subject":"Re: Minor annoyance with git push","fromName":"Steven Walter","fromEmail":"stevenrwalter@gmail.com","sentAt":"2008-02-21T22:35:49Z","receivedAt":"2008-02-21T22:35:49Z","isPatch":false,"sender":{"key":"stevenrwalter@gmail.com","avatar":"https://avatars.githubusercontent.com/u/79127?v=4"},"body":"On Wed, Feb 20, 2008 at 03:38:31PM +0000, Johannes Schindelin wrote:\n> That depends awfully on your definition of \"safe\".\n> \n> I, for one, hate the idea already, that I am \"safe\" when \"git push\" does \n> not do the thing I asked it to, and which it has done for a couple of \n> years now without complaint, and which I have gotten used to.\n> \n> And then, there will be a great confusion for me, since I work on 5 \n> different machines on an average day, with 5 different git versions, and \n> having different config settings.\n\nWhich is worse: pushing more refs than you intended (requiring rewinding\nrefs on a repository that other people may pull from), or pushing fewer\nrefs than you intended, requiring you to run the command a second time?\n-- \n-Steven Walter <stevenrwalter@gmail.com>\nFreedom is the freedom to say that 2 + 2 = 4\nB2F1 0ECC E605 7321 E818  7A65 FC81 9777 DC28 9E8F \n"},{"id":"69541","messageId":"alpine.LSU.1.00.0802220010260.17164@racer.site","threadId":"11961","inReplyTo":"20080221223549.GA26266@dervierte","subject":"Re: Minor annoyance with git push","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-22T00:11:25Z","receivedAt":"2008-02-22T00:11:25Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 21 Feb 2008, Steven Walter wrote:\n\n> On Wed, Feb 20, 2008 at 03:38:31PM +0000, Johannes Schindelin wrote:\n> > That depends awfully on your definition of \"safe\".\n> > \n> > I, for one, hate the idea already, that I am \"safe\" when \"git push\" \n> > does not do the thing I asked it to, and which it has done for a \n> > couple of years now without complaint, and which I have gotten used \n> > to.\n> > \n> > And then, there will be a great confusion for me, since I work on 5 \n> > different machines on an average day, with 5 different git versions, \n> > and having different config settings.\n> \n> Which is worse: pushing more refs than you intended (requiring rewinding \n> refs on a repository that other people may pull from), or pushing fewer \n> refs than you intended, requiring you to run the command a second time? \n\nSorry to say, but I find this argumentation lacking.\n\nIs it worse to suffer, or is it worse to suffer?  We should try to make it \n_safe_ not \"less painful, but still painful nevertheless\".\n\nHth,\nDscho\n"}]}