{"thread":{"id":"28469","subject":"More Beginning Git Questions","startedAt":"2011-09-23T14:41:49Z","lastAt":"2011-09-26T18:03:59Z","messageCount":24,"participants":["Jon Forrest","Matthieu Moy","Jakub Narebski","Mihamina Rakotomandimby","Junio C Hamano","tactical","Frans Klaver","Seth Robertson","Konstantin Khomoutov","Andrew Ardill"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"176067","messageId":"4E7C9AAD.7060209@gmail.com","threadId":"28469","inReplyTo":null,"subject":"More Beginning Git Questions","fromName":"Jon Forrest","fromEmail":"nobozo@gmail.com","sentAt":"2011-09-23T14:41:49Z","receivedAt":"2011-09-23T14:41:49Z","isPatch":false,"sender":{"key":"nobozo@gmail.com","avatar":"https://gravatar.com/avatar/37c6a7b57f29b3f35c6a9016537907c52f15bbf98575617dc046bcec6bf06372?d=mp&s=160"},"body":"I'm reading the git tutorial at\nhttp://schacon.github.com/git/gittutorial.html\nI'm a very literal reader so if something isn't clear\nto me, I try to make the effort to understand it.\n\nIn reading about what happens when Alice pulls from Bob,\nit says:\n\n\"Note that in general, Alice would want her local changes committed \nbefore initiating this \"pull\".\"\n\nThis is an interesting statement. I'll come back to it shortly.\n\n\"If Bob’s work conflicts with what Alice did since their histories forked,\"\n\nDoes this include both changes that Alice has checked in to\nher repository and uncommitted changes in her working tree?\n\n\"Alice will use her working tree and the index to resolve conflicts,\"\n\nHow does Alice use her working tree and index? Does this mean\nshe makes changes to her working tree so that the conflicts\nno longer exist? How does the index play a part in this?\nI thought that the index gets populated only when a\n\"git add\" is done. Does Alice need to do \"git add\" as part\nof the conflict resolution process?\n\n\"and existing local changes will interfere with the conflict resolution \nprocess\"\n\nAre \"local changes\" the changes in the working tree, the\nuncommitted changes that Alice has added to her index, or\nchanges that Alice has committed to her local repository?\n\n\"(git will still perform the fetch but will refuse to merge\n--- Alice will have to get rid of her local changes in\nsome way and pull again when this happens).\"\n\nAgain, I'm not clear on which local changes this is talking\nabout. In other words, when the merge part of the pull is\ndone, what is examined locally? The first sentence about\nAlice committing her local changes before pulling is what\ngot me thinking about all this.\n\nI'm sorry if these are too pedantic.\n\nJon Forrest\n"},{"id":"176072","messageId":"vpq62kjw854.fsf@bauges.imag.fr","threadId":"28469","inReplyTo":"4E7C9AAD.7060209@gmail.com","subject":"Re: More Beginning Git Questions","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-09-23T16:11:51Z","receivedAt":"2011-09-23T16:11:51Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jon Forrest <nobozo@gmail.com> writes:\n\n> \"If Bob’s work conflicts with what Alice did since their histories forked,\"\n>\n> Does this include both changes that Alice has checked in to\n> her repository and uncommitted changes in her working tree?\n\nGit will not allow you to do a \"git pull\" if your uncommited changes\ntouch the same files as the pull. So, you basically can't have conflicts\nabout uncommited changes with \"git pull\".\n\nThat's by design: solving conflicts can be hard, and you want the \"last\ncommit\" safety net while doing it. If you mess up your conflict\nresolution, you can still \"git reset --merge\" and try again.\n\n> \"Alice will use her working tree and the index to resolve conflicts,\"\n>\n> How does Alice use her working tree and index? Does this mean\n> she makes changes to her working tree so that the conflicts\n> no longer exist?\n\nYes.\n\n> How does the index play a part in this?\n\nOnce the conflict is fixed in the working tree, you run \"git add\" to\nmark the conflict as resolved.\n\nAnd before this, the index contains half-merged versions of your file,\nand \"git diff\" can show you the difference between them and your\nworktree. See the user manual :\n\nhttp://schacon.github.com/git/user-manual.html#resolving-a-merge\n\n(BTW, that's not the official place for Git documentation, but since\nkernel.org is down now ...)\n\n> \"and existing local changes will interfere with the conflict\n> resolution process\"\n\nProbably this should have been \"would have interfered\" (and therefore\nare forbidden by Git, as the following sentence says):\n\n> \"(git will still perform the fetch but will refuse to merge\n> --- Alice will have to get rid of her local changes in\n> some way and pull again when this happens).\"\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"176077","messageId":"m3ipojqhpm.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"4E7C9AAD.7060209@gmail.com","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-23T17:42:18Z","receivedAt":"2011-09-23T17:42:18Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jon Forrest <nobozo@gmail.com> writes:\n\n> I'm reading the git tutorial at\n> http://schacon.github.com/git/gittutorial.html\n\nI recommend reading \"Pro Git\" book (http://progit.org)\n\n> I'm a very literal reader so if something isn't clear\n> to me, I try to make the effort to understand it.\n> \n> In reading about what happens when Alice pulls from Bob,\n> it says:\n> \n> \"Note that in general, Alice would want her local changes committed\n> before initiating this \"pull\".\"\n> \n> This is an interesting statement. I'll come back to it shortly.\n> \n> \"If Bobs work conflicts with what Alice did since their histories forked,\"\n> \n> Does this include both changes that Alice has checked in to\n> her repository and uncommitted changes in her working tree?\n\nGenerally Alice shouldn't have uncommitted changes when doing\n\"git pull\".\n\n> \"Alice will use her working tree and the index to resolve conflicts,\"\n> \n> How does Alice use her working tree and index? Does this mean\n> she makes changes to her working tree so that the conflicts\n> no longer exist? How does the index play a part in this?\n> I thought that the index gets populated only when a\n> \"git add\" is done. Does Alice need to do \"git add\" as part\n> of the conflict resolution process?\n\nThis is actually a very important information.\n\nWhen there is a merge conflicts, the index gets populated by more than\none version: \"ours\" (i.e. Alice version) in stage 2, \"theirs\"\n(i.e. Bob version) in stage 3, and \"base\" (common ancestor version) in\nstage 1.  The stage 0, where \"git add\" / \"git stage\" puts contents of\nfile, is empty.\n\nYou can see it using \"git ls-files --abbrev --stage\".\n \nThe working area gets populated with version that contains both \"ours\"\nand \"theirs\" hunks using conflict markers (the 3-way textual merge,\nlike 'rcsmerge' or 'diff3 -E' does).  Sidenote: you can use \"git\ncheckout --conflict=merge <file>\" to re-create this version if you\nmessed up conflict resolution, or even --conflict=diff3 if you want\n\"base\" (ancestor) version to be shown in conflict markers as\nwell... but this would discard your changes.\n\nAfter resolving conflict you do \"git add\" on resolved file to mark it\nas done.  This leaves you with only newly add-ed stage 0 in the index!\n\nThe pre-commit hook might check if you didn't accidentally marked as\nresolved (added) file with [something that looks like] conflict\nmarkers in it.\n\nHTH\n-- \nJakub Narębski\n"},{"id":"176082","messageId":"4E7CCCA0.50909@gmail.com","threadId":"28469","inReplyTo":"m3ipojqhpm.fsf@localhost.localdomain","subject":"Re: More Beginning Git Questions","fromName":"Jon Forrest","fromEmail":"nobozo@gmail.com","sentAt":"2011-09-23T18:14:56Z","receivedAt":"2011-09-23T18:14:56Z","isPatch":false,"sender":{"key":"nobozo@gmail.com","avatar":"https://gravatar.com/avatar/37c6a7b57f29b3f35c6a9016537907c52f15bbf98575617dc046bcec6bf06372?d=mp&s=160"},"body":"On 9/23/2011 10:42 AM, Jakub Narebski wrote:\n\n> I recommend reading \"Pro Git\" book (http://progit.org)\n\nI'm reading that too. I have some similar pedantic questions\nabout that book but I don't want to be a pest so I'll\nstick with the tutorial now. Maybe some of my questions\nabout \"Pro Git\" will get answered.\n\n>> Does this include both changes that Alice has checked in to\n>> her repository and uncommitted changes in her working tree?\n>\n> Generally Alice shouldn't have uncommitted changes when doing\n> \"git pull\".\n\nThat's what the tutorial said but I'm trying to understand\nwhat happens if she does have uncommitted changes. I'm\ntrying to understand the total picture.\n\n> When there is a merge conflicts, the index gets populated by more than\n> one version: \"ours\" (i.e. Alice version) in stage 2, \"theirs\"\n> (i.e. Bob version) in stage 3, and \"base\" (common ancestor version) in\n> stage 1.  The stage 0, where \"git add\" / \"git stage\" puts contents of\n> file, is empty.\n\nI didn't know there were multiple staging areas.\n\n> You can see it using \"git ls-files --abbrev --stage\".\n\nThat's very helpful.\n\nThanks to (almost) everyone who has responded. I'm hoping that\nothers new to Git will benefit from this discussion.\n\nJon\n"},{"id":"176084","messageId":"4E7CD39D.60205@rktmb.org","threadId":"28469","inReplyTo":"4E7CCCA0.50909@gmail.com","subject":"Re: More Beginning Git Questions","fromName":"Mihamina Rakotomandimby","fromEmail":"mihamina@rktmb.org","sentAt":"2011-09-23T18:44:45Z","receivedAt":"2011-09-23T18:44:45Z","isPatch":false,"sender":{"key":"mihamina@rktmb.org","avatar":"https://gravatar.com/avatar/b52e5d85625fd27eecfea3f3fa827a29140ac806bbdb29d0d79088a55e046a17?d=mp&s=160"},"body":"On 09/23/2011 09:14 PM, Jon Forrest wrote:\n>\n> Thanks to (almost) everyone who has responded. I'm hoping that\n> others new to Git will benefit from this discussion.\n\nIt does, it does...\nI'm working on an internal parallel documentation on using Hg and Git \nand this conflict resolution topic is... important.\n\n-- \nRMA.\n"},{"id":"176086","messageId":"7vipojumd0.fsf@alter.siamese.dyndns.org","threadId":"28469","inReplyTo":"4E7C9AAD.7060209@gmail.com","subject":"Re: More Beginning Git Questions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-09-23T18:47:39Z","receivedAt":"2011-09-23T18:47:39Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jon Forrest <nobozo@gmail.com> writes:\n\n> \"Note that in general, Alice would want her local changes committed\n> before initiating this \"pull\".\"\n>\n> This is an interesting statement. I'll come back to it shortly.\n>\n> \"If Bob’s work conflicts with what Alice did since their histories forked,\"\n>\n> Does this include both changes that Alice has checked in to her\n> repository and uncommitted changes in her working tree?\n\nWe do not consider uncommitted changes part of _any_ history. You can\nthink of them as floating on top of the history of the branch that is\ncurrently checked out [*1*].\n\n> \"Alice will use her working tree and the index to resolve conflicts,\"\n>\n> How does Alice use her working tree and index? Does this mean\n> she makes changes to her working tree so that the conflicts\n> no longer exist? How does the index play a part in this?\n>\n> I thought that the index gets populated only when a\n> \"git add\" is done. Does Alice need to do \"git add\" as part\n> of the conflict resolution process?\n\nIf you start from a clean working tree (i.e. no local changes), then after\nany \"mergy\" operation (not just \"git pull\" and \"git merge\" but things like\n\"cherry-pick\", \"checkout -m\", \"rebase\" and \"am -3\" that can stop due to\nconflicts), one of the three things will happen to each of the paths in\nthe project:\n\n 1. If the result of the operation can be mechanically known, and if that\n    is the same as your current state (i.e. HEAD or \"ours\"), nothing\n    happens.\n\n 2. If the result of the operation can be mechanically known, and if that\n    is different from your current state (i.e. HEAD or \"ours\"), the index\n    entry for that path records the result, and the path in the working\n    tree is updated to match that result.\n\n 3. If the result of the operation cannot be mechanically known\n    (i.e. merge conflict), the index entry for that path will record up to\n    3 \"stages\", stage #1 representing the contents the conflicting sides\n    diverged from (i.e. common ancestor), stage #2 representing the\n    contents of your current state (i.e. HEAD or \"ours\") and stage #3\n    representing the contents of the other branch (i.e. MERGE_HEAD or\n    \"theirs\"), and the path in the working tree is updated to represent it\n    with conflict markers.\n\nYou conclude the \"mergy\" operation by resolving conflicts in the working\ntree for paths in the category 3, tell Git that you are done with these\npaths using \"git add $path\" (but paths in no other categories!!!).\nBecause cleanly merged paths are already updated in the index (see\n2. above), that is all needed to bring the index to the state that\nrepresents the desired result of the \"mergy\" operation.\n\nEven if you have local changes in your working tree, as long as your index\nexactly matches HEAD when you start your \"mergy\" operation, thanks to the\nrule for \"result matches the current HEAD\" case (see 1. above), the result\nof your \"mergy\" operation recorded by the procedure in the previous\nparagraph will not be contaminated with your local changes.\n\nThe precondition for all of the above to work is that you start from a\nclean index, and that is why \"git merge\" refuses to start if your index\nalready has changes relative to HEAD.\n\nAlso, for cases 2. and 3., updating the files in the working tree to match\nthe auto-merge result (case 2.) or to show the conflicted state (case 3.)\nrequires Git to overwrite the file, which is bad if you have local changes\nto the files in the working tree. To prevent lossage, \"mergy\" operations\nwill notice if paths in categories 2. and 3. have local changes in the\nworking tree, and refuses to work if that is the case.\n\n\n[Footnote]\n\n*1* This incidentally is important to have in your mental model to\nunderstand how to use \"git checkout $branch\" to switch branches.\n"},{"id":"176087","messageId":"m3ehz7qe5a.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"4E7CCCA0.50909@gmail.com","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-23T18:59:22Z","receivedAt":"2011-09-23T18:59:22Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"BTW it is customary on git mailing list to send reply not only to git\nmailing list, but also to all responders (to previous author, cc to\nlist and to others).\n\nJon Forrest <nobozo@gmail.com> writes:\n> On 9/23/2011 10:42 AM, Jakub Narebski wrote:\n>> Jon Forrest <nobozo@gmail.com> writes:\n \n>>> Does this include both changes that Alice has checked in to\n>>> her repository and uncommitted changes in her working tree?\n>>\n>> Generally Alice shouldn't have uncommitted changes when doing\n>> \"git pull\".\n> \n> That's what the tutorial said but I'm trying to understand\n> what happens if she does have uncommitted changes. I'm\n> trying to understand the total picture.\n\nIf Alice have uncommitted changes, in working tree and/or in the\nindex, what git does is try to merge if possible; if conflict or new\nversions from \"theirs\" touch changed file, git refuses to do a merge.\n \nThe idea is to do merge if possible, but abort if there is any chance\nthat user's changes would be lost.\n\n>> When there is a merge conflicts, the index gets populated by more than\n>> one version: \"ours\" (i.e. Alice version) in stage 2, \"theirs\"\n>> (i.e. Bob version) in stage 3, and \"base\" (common ancestor version) in\n>> stage 1.  The stage 0, where \"git add\" / \"git stage\" puts contents of\n>> file, is empty.\n> \n> I didn't know there were multiple staging areas.\n\nThose are called \"stages\" inside one single staging area (the index).\n \n>> You can see it using \"git ls-files --abbrev --stage\".\n> \n> That's very helpful.\n\nAlso in the case of conflict, \"git diff\" would show combined diff of\nchanges.\n\nTry both on some example.\n\n-- \nJakub Narębski\n"},{"id":"176138","messageId":"14gm3o851q0ad.1uoossmxgfyit.dlg@40tude.net","threadId":"28469","inReplyTo":"4E7CCCA0.50909@gmail.com","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-24T20:22:31Z","receivedAt":"2011-09-24T20:22:31Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Jon Forrest wrote:\n\n>> Generally Alice shouldn't have uncommitted changes when doing\n>> \"git pull\".\n> \n> That's what the tutorial said but I'm trying to understand\n> what happens if she does have uncommitted changes. I'm\n> trying to understand the total picture.\n\nMercurial allows this, and it's a very powerful feature.  After reading \nthis thread, I could not believe Git didn't pulling with local changes, and \nso I tried it, and also asked on IRC -- and it seems that Git really \ndoesn't.\n\nIf this is an important part of your workflow (as it is mine), I'd \nrecommend using Mercurial if possible.\n"},{"id":"176139","messageId":"op.v2byz2p80aolir@keputer.lokaal","threadId":"28469","inReplyTo":"14gm3o851q0ad.1uoossmxgfyit.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Frans Klaver","fromEmail":"fransklaver@gmail.com","sentAt":"2011-09-24T20:53:52Z","receivedAt":"2011-09-24T20:53:52Z","isPatch":false,"sender":{"key":"fransklaver@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1876483?v=4"},"body":"On Sat, 24 Sep 2011 22:22:31 +0200, tactical <a5158017@nepwk.com> wrote:\n\n> Mercurial allows this, and it's a very powerful feature.  After reading\n> this thread, I could not believe Git didn't pulling with local changes,  \n> and so I tried it, and also asked on IRC -- and it seems that Git really\n> doesn't.\n\nGit doesn't do it implicitly. Be explicit about it\n\n$ git stash\n$ git pull\n$ git stash pop\n\nseems to do exactly what you want.\n\nCheers,\nFrans\n"},{"id":"176140","messageId":"m362khr6kh.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"14gm3o851q0ad.1uoossmxgfyit.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-24T21:10:07Z","receivedAt":"2011-09-24T21:10:07Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"tactical <a5158017@nepwk.com> writes:\n> Jon Forrest wrote:\n> > Jakub Narebski wrote:\n \n> > > Generally Alice shouldn't have uncommitted changes when doing\n> > > \"git pull\".\n> > \n> > That's what the tutorial said but I'm trying to understand\n> > what happens if she does have uncommitted changes. I'm\n> > trying to understand the total picture.\n> \n> Mercurial allows this, and it's a very powerful feature.\n\nYou *do* realize thet \"hg pull\" is \"git fetch\", don't you?\n\n>  After reading \n> this thread, I could not believe Git didn't pulling with local changes, and \n> so I tried it, and also asked on IRC -- and it seems that Git really \n> doesn't.\n> \n> If this is an important part of your workflow (as it is mine), I'd \n> recommend using Mercurial if possible.\n> \n\nSo the question is if mercurial allows _merging_ with local\nchanges... and from the thread it looks like git dies allow it, as\nlong as changes are isolated from changes brought by merge.\n\nAnyway merging with local changes is an easy way to f**k up your\nchanges in unrecoverable way, IMVHO...\n\n-- \nJakub Narębski\n"},{"id":"176143","messageId":"nbd7plmz30x2.mafpxaq9xl9r.dlg@40tude.net","threadId":"28469","inReplyTo":"m362khr6kh.fsf@localhost.localdomain","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-24T22:10:14Z","receivedAt":"2011-09-24T22:10:14Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Jakub Narebski wrote:\n\n>>> > Generally Alice shouldn't have uncommitted changes when doing\n>>> > \"git pull\".\n>>> \n>>> That's what the tutorial said but I'm trying to understand\n>>> what happens if she does have uncommitted changes. I'm\n>>> trying to understand the total picture.\n>> \n>> Mercurial allows this, and it's a very powerful feature.\n> \n> You *do* realize thet \"hg pull\" is \"git fetch\", don't you?\n\nYes.  This is what I mean:\n\n    c:\\test>hg diff\n\n    diff --git a/foo b/foo\n    --- a/foo\n    +++ b/foo\n    @@ -1,1 +1,2 @@\n     test\n    +new line\n\n    c:\\test>hg incoming --patch clone\n\n    comparing with clone\n    searching for changes\n    changeset:   1:0a897c3462a8\n    tag:         tip\n    user:        tactical\n    date:        Sat Sep 24 23:03:21 2011 +0100\n    summary:     bar\n\n    diff --git a/foo b/foo\n    --- a/foo\n    +++ b/foo\n    @@ -1,1 +1,2 @@\n     test\n    +bar\n\n    c:\\test>hg pull clone\n\n    pulling from clone\n    searching for changes\n    adding changesets\n    adding manifests\n    adding file changes\n    added 1 changesets with 1 changes to 1 files\n    (run 'hg update' to get a working copy)\n\n    c:\\test>hg update\n\n    merging foo\n\nNow KDiff3 automagically appears (because of the line conflict).\n\n>>  After reading \n>> this thread, I could not believe Git didn't pulling with local changes, and \n>> so I tried it, and also asked on IRC -- and it seems that Git really \n>> doesn't.\n>> \n>> If this is an important part of your workflow (as it is mine), I'd \n>> recommend using Mercurial if possible.\n>> \n> \n> So the question is if mercurial allows _merging_ with local\n> changes... and from the thread it looks like git dies allow it, as\n> long as changes are isolated from changes brought by merge.\n\nFor that reason, Git doesn't support my workflow at all.\n\n> Anyway merging with local changes is an easy way to f**k up your\n> changes in unrecoverable way, IMVHO...\n\nMercurial backs everything up before doing this merge, so if I do lose my\nlocal changes, I can start over with this:\n\n    hg resolve --unmark --all\n    hg resolve --all\n\nNow KDiff3 comes up again, with the same data as before.  No data lost.\n"},{"id":"176144","messageId":"1m2c90ds9e46c.7agk88pbgjl8$.dlg@40tude.net","threadId":"28469","inReplyTo":"op.v2byz2p80aolir@keputer.lokaal","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-24T22:17:35Z","receivedAt":"2011-09-24T22:17:35Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Frans Klaver wrote:\n\n>> Mercurial allows this, and it's a very powerful feature.  After reading\n>> this thread, I could not believe Git didn't pulling with local changes,  \n>> and so I tried it, and also asked on IRC -- and it seems that Git really\n>> doesn't.\n> \n> Git doesn't do it implicitly. Be explicit about it\n> \n> $ git stash\n> $ git pull\n> $ git stash pop\n> \n> seems to do exactly what you want.\n\nDoes popping the stash allow for a three-way merge?  If not, this doesn't\nreally solve the problem.\n\nThanks\n"},{"id":"176146","messageId":"201109242259.p8OMxqIM026259@no.baka.org","threadId":"28469","inReplyTo":"1m2c90ds9e46c.7agk88pbgjl8$.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Seth Robertson","fromEmail":"in-gitvger@baka.org","sentAt":"2011-09-24T22:59:52Z","receivedAt":"2011-09-24T22:59:52Z","isPatch":false,"sender":{"key":"in-gitvger@baka.org","avatar":null},"body":"\nIn message <1m2c90ds9e46c.7agk88pbgjl8$.dlg@40tude.net>, tactical writes:\n\n    Frans Klaver wrote:\n\n    >> Mercurial allows this, and it's a very powerful feature.  After reading\n    >> this thread, I could not believe Git didn't pulling with local changes,\n    >> and so I tried it, and also asked on IRC -- and it seems that Git really\n    >> doesn't.\n    >\n    > Git doesn't do it implicitly. Be explicit about it\n    >\n    > $ git stash\n    > $ git pull\n    > $ git stash pop\n    >\n    > seems to do exactly what you want.\n\n    Does popping the stash allow for a three-way merge?  If not, this doesn't\n    really solve the problem.\n\nAs I explained on IRC, you can use the following workflow to create a\nthree way merge.\n\ngit stash\ngit fetch\ngit merge @{u} stash\ngit mergetool\ngit stash drop\n\nYou can then do whatever other work you want.  You can repeat this\nworkflow as often as you want.  When you are done, then you can\ncommit:\n\ngit commit -a -m \"My important work\"\n\nThis is of course easily scriptable so it becomes one command to you.\nAnd since you mentioned it, if the merge went poorly and you wanted to\nstart over (only before you dropped the stash of course), you can:\n\ngit reset --hard HEAD\ngit merge @{u} stash\n\nAnd then continue with the rest of the workflow above.\n\n\nOf course, I would recommend you consider some of the more gitish\nworkflows.  Commit early and often.  `git pull --rebase` as often as\nyou want, and then use `git rebase -i @{u}^` to squash all of your\nin-progress commits together.  With appropriate in-progress commit\nmessage crafting, you can use the --autosquash functionality of\ngit-rebase to make this process easier.\n\n\t\t\t\t\t-Seth Robertson\n"},{"id":"176150","messageId":"1wllqv48uqfjq.lt9yp4rbxugb.dlg@40tude.net","threadId":"28469","inReplyTo":"201109242259.p8OMxqIM026259@no.baka.org","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-25T02:16:06Z","receivedAt":"2011-09-25T02:16:06Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Seth Robertson wrote:\n\n> As I explained on IRC, you can use the following workflow to create a\n> three way merge.\n> \n> git stash\n> git fetch\n> git merge @{u} stash\n> git mergetool\n> git stash drop\n> \n> You can then do whatever other work you want.  You can repeat this\n> workflow as often as you want.  When you are done, then you can\n> commit:\n> \n> git commit -a -m \"My important work\"\n> \n> This is of course easily scriptable so it becomes one command to you.\n> And since you mentioned it, if the merge went poorly and you wanted to\n> start over (only before you dropped the stash of course), you can:\n> \n> git reset --hard HEAD\n> git merge @{u} stash\n\nThanks.  It's a shame, however, that Git makes the user jump through hoops\nto achieve such a simple thing.\n\n> Of course, I would recommend you consider some of the more gitish\n> workflows.\n\nAnd that, I feel, is a problem with Git.  In some cases, you can't do\nthings how you want -- you have to do things how Git wants.\n\nAnother example of this is the lack of support for anonymous branching as\npart of a normal workflow in Git.  Anonymous branching is very powerful and\nvery simple.  I use it all the time in Mercurial.\n\n> Commit early and often.  `git pull --rebase` as often as\n> you want, and then use `git rebase -i @{u}^` to squash all of your\n> in-progress commits together.  With appropriate in-progress commit\n> message crafting, you can use the --autosquash functionality of\n> git-rebase to make this process easier.\n\nThanks for the ideas, but they don't solve my particular problem.  The\nreason I regularly pull with local changes is that I like to use clones for\nshort-term branching (because it's powerful and flexible -- for example,\nwhen I create my \"TryFeatureX\" clone, I have two versions of my project on\ndisk, and I can run them side by side).\n\nIn order to avoid pointless merges, I sometimes don't commit until I've\npulled.  Sure, I could commit and then rebase instead, but, in this\nsituation, rebasing is effectively merging and committing in one step.\nWith my workflow, however, after I merge, I can still make changes (and do\nother stuff like running unit tests) before finally committing.\n"},{"id":"176165","messageId":"m31uv4rc47.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"1wllqv48uqfjq.lt9yp4rbxugb.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-25T13:22:29Z","receivedAt":"2011-09-25T13:22:29Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"tactical <a5158017@nepwk.com> writes:\n> Seth Robertson wrote:\n> \n> > As I explained on IRC, you can use the following workflow to create a\n> > three way merge.\n> > \n> > git stash\n> > git fetch\n> > git merge @{u} stash\n> > git mergetool\n> > git stash drop\n> > \n> > You can then do whatever other work you want.  You can repeat this\n> > workflow as often as you want.  When you are done, then you can\n> > commit:\n> > \n> > git commit -a -m \"My important work\"\n> > \n> > This is of course easily scriptable so it becomes one command to you.\n> > And since you mentioned it, if the merge went poorly and you wanted to\n> > start over (only before you dropped the stash of course), you can:\n> > \n> > git reset --hard HEAD\n> > git merge @{u} stash\n> \n> Thanks.  It's a shame, however, that Git makes the user jump through hoops\n> to achieve such a simple thing.\n\nA short time after \"git stash\" was added to Git there was proposal to\nautomatically use git stash to allow merging with \"dirty tree\",\ni.e. with uncomitted changes.  This idea was abandoned, if I remember\nit correctly because a.) there were too many corner-cases b.) it\nwasn't necessary in most cases.\n \nWith merging into branch with uncomitted changes your fairly well\nunderstood 3-way merge (sometimes virtual 3-way merge in the case of\nmultiple common ancestors) would turn into 4-way merge.  Even if you\ncan automate it somehow (I do wonder how Mercurial manages that),\nthere could be problem resolving conflicts, unless you happen to touch\ndifferent parts of file.\n\n> > Of course, I would recommend you consider some of the more gitish\n> > workflows.\n> \n> And that, I feel, is a problem with Git.  In some cases, you can't do\n> things how you want -- you have to do things how Git wants.\n\nPlease take into account the fact that when you were creating your\nworkflow to suit your situation you were \"forced\" to fit it to\nMercurial abilities and best practices.  No wonder that it does not\nfit Git-ish workflows.\n\nWhat you use uncomitted changes for, I would use is a separate branch,\nand keep it rebasing (something like using 'mq' in Mercurial).\n \n> Another example of this is the lack of support for anonymous branching as\n> part of a normal workflow in Git.  Anonymous branching is very powerful and\n> very simple.  I use it all the time in Mercurial.\n\nWhat do you use anonymous branching for?\n\nNote that with Git by default pushing \"matching\" branches, you can\ncreate private local-only branches.  The have to have _some_ name\n(even if it is 'foo/temp'), but I think that it makes them perhaps\nmore work to create, but easier to use (to switch branches)... and for\nsingle anonymous branch you can always use \"detached HEAD\".\n \n-- \nJakub Narębski\n"},{"id":"176166","messageId":"m3wrcwpxh7.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"nbd7plmz30x2.mafpxaq9xl9r.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-25T13:24:00Z","receivedAt":"2011-09-25T13:24:00Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"tactical <a5158017@nepwk.com> writes:\n> Jakub Narebski wrote:\n\n> > Anyway merging with local changes is an easy way to f**k up your\n> > changes in unrecoverable way, IMVHO...\n> \n> Mercurial backs everything up before doing this merge, so if I do lose my\n> local changes, I can start over with this:\n> \n>     hg resolve --unmark --all\n>     hg resolve --all\n\nWell, that's the advantage of database-like transaction based atomic\noperations.\n\nOTOH reflog allows to back out not only last operation...\n\n-- \nJakub Narębski\n"},{"id":"176178","messageId":"1rwoliveqwr1v.u3bsx5axtgsb$.dlg@40tude.net","threadId":"28469","inReplyTo":"m31uv4rc47.fsf@localhost.localdomain","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-25T20:23:00Z","receivedAt":"2011-09-25T20:23:00Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Jakub Narebski wrote:\n\n> With merging into branch with uncomitted changes your fairly well\n> understood 3-way merge (sometimes virtual 3-way merge in the case of\n> multiple common ancestors) would turn into 4-way merge.\n\nI don't see why it would be a four-way merge rather than a three-way merge.\n\n> Even if you\n> can automate it somehow (I do wonder how Mercurial manages that),\n> there could be problem resolving conflicts, unless you happen to touch\n> different parts of file.\n\nThis behaviour is by design in Mercurial.  It's simple, and it works.  I've\nnever had a problem with resolving conflicts here, and I don't see why I\never would.\n\n>> And that, I feel, is a problem with Git.  In some cases, you can't do\n>> things how you want -- you have to do things how Git wants.\n> \n> Please take into account the fact that when you were creating your\n> workflow to suit your situation you were \"forced\" to fit it to\n> Mercurial abilities and best practices.  No wonder that it does not\n> fit Git-ish workflows.\n\nNo, I came to the distributed world only recently, from Subversion.  I\nchoose to use clones over plain anonymous branching, over bookmarks, and\nover named branching because I prefer the approach.  I can, of course, do\n\"Git branching\" in Mercurial very easily if I want (with Mercurial\nbookmarks).\n\n> What you use uncomitted changes for, I would use is a separate branch,\n> and keep it rebasing (something like using 'mq' in Mercurial).\n\nYes, but, as I mentioned, rebasing is less flexible.  A rebase here is\neffectively a merge and a commit in one step, whereas my approach separates\nthe merge and the commit.\n\n>> Another example of this is the lack of support for anonymous branching as\n>> part of a normal workflow in Git.  Anonymous branching is very powerful and\n>> very simple.  I use it all the time in Mercurial.\n> \n> What do you use anonymous branching for?\n\nAnonymous branching is great for minor divergence that isn't really\nsignificant enough to deserve a name.  It's also great for branches that\n*are* significant enough to deserve a name, but where you want to defer\nnaming the branch right up until you merge it into another branch.  At that\npoint you can 'name' the branch in the commit message.  (Of course, you\ncould also create a Mercurial bookmark at that point, and then you'd\nessentially have a \"Git branch\".)\n\n> Note that with Git by default pushing \"matching\" branches, you can\n> create private local-only branches.  The have to have _some_ name\n> (even if it is 'foo/temp'), but I think that it makes them perhaps\n> more work to create, but easier to use (to switch branches)... and for\n> single anonymous branch you can always use \"detached HEAD\".\n\n>From what I read, detached heads are subject to garbage collection.\n"},{"id":"176180","messageId":"m3oby8pcfz.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"1rwoliveqwr1v.u3bsx5axtgsb$.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-25T20:58:18Z","receivedAt":"2011-09-25T20:58:18Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"tactical <a5158017@nepwk.com> writes:\n> Jakub Narebski wrote:\n> \n> > With merging into branch with uncomitted changes your fairly well\n> > understood 3-way merge (sometimes virtual 3-way merge in the case of\n> > multiple common ancestors) would turn into 4-way merge.\n> \n> I don't see why it would be a four-way merge rather than a three-way merge.\n\nYou have four version: \"base\" (ancestor version), \"theirs\"\n(branch/clone being merged), \"ours\" (comitted changes on current\nbranch) and \"new\" (uncomitted changes on current branch).\n\nUnless Mercurial does 3-way merge of \"new\", \"theirs\" and \"base\"...\nwith transaction based atomicity (saving \"new\" before attempting\nmerge) they can do that.\n\nWith Git you have additional complication: the index state.\n\n> > Even if you\n> > can automate it somehow (I do wonder how Mercurial manages that),\n> > there could be problem resolving conflicts, unless you happen to touch\n> > different parts of file.\n> \n> This behaviour is by design in Mercurial.  It's simple, and it works.  I've\n> never had a problem with resolving conflicts here, and I don't see why I\n> ever would.\n\nIt if really is 3-way merge, you wouldn't.  If it isn't (e.g. it is\n3-way merge + applying patch, like merge + stash apply in git), then\nthere are [nasty] corner cases.\n \nAnyway I hope that Mercurial does test this feature extensively.\n\n[...]\n> > What you use uncomitted changes for, I would use is a separate branch,\n> > and keep it rebasing (something like using 'mq' in Mercurial).\n> \n> Yes, but, as I mentioned, rebasing is less flexible.  A rebase here is\n> effectively a merge and a commit in one step, whereas my approach separates\n> the merge and the commit.\n\nErrr... what?  You first commit your changes, then keep it rebasing to\nkeep them up to date on top of fresh version.\n \n> > > Another example of this is the lack of support for anonymous branching as\n> > > part of a normal workflow in Git.  Anonymous branching is very powerful and\n> > > very simple.  I use it all the time in Mercurial.\n> > \n> > What do you use anonymous branching for?\n> \n> Anonymous branching is great for minor divergence that isn't really\n> significant enough to deserve a name.  It's also great for branches that\n> *are* significant enough to deserve a name, but where you want to defer\n> naming the branch right up until you merge it into another branch.  At that\n> point you can 'name' the branch in the commit message.\n\nI think you can use detached HEAD for that, at least when working on\none issue at a time (you have to name branch when switching to some\nother work).\n\n> (Of course, you\n> could also create a Mercurial bookmark at that point, and then you'd\n> essentially have a \"Git branch\".)\n\nExcept for the fact that AFAIK Mercurial bookmarks have single global\nnamespace for branch (bookmark) names, while Git uses more flexible\nbut less newbie-user-friendly branch to remote-tracking branch name\nmapping via \"refspec\".\n \n> > Note that with Git by default pushing \"matching\" branches, you can\n> > create private local-only branches.  The have to have _some_ name\n> > (even if it is 'foo/temp'), but I think that it makes them perhaps\n> > more work to create, but easier to use (to switch branches)... and for\n> > single anonymous branch you can always use \"detached HEAD\".\n> \n> From what I read, detached heads are subject to garbage collection.\n \nNo, HEAD is protected against garbage collecting.  To be sure you\nshould name a branch when switching branches, though reflog would\nprotect you for 30 days (by default) even if you don't do that.\n\n-- \nJakub Narębski\n"},{"id":"176181","messageId":"1ttmqsxtaj98i$.hv6s5shjeugr.dlg@40tude.net","threadId":"28469","inReplyTo":"m3oby8pcfz.fsf@localhost.localdomain","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-25T21:07:24Z","receivedAt":"2011-09-25T21:07:24Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Jakub Narebski wrote:\n\n>>> With merging into branch with uncomitted changes your fairly well\n>>> understood 3-way merge (sometimes virtual 3-way merge in the case of\n>>> multiple common ancestors) would turn into 4-way merge.\n>> \n>> I don't see why it would be a four-way merge rather than a three-way merge.\n> \n> You have four version: \"base\" (ancestor version), \"theirs\"\n> (branch/clone being merged), \"ours\" (comitted changes on current\n> branch) and \"new\" (uncomitted changes on current branch).\n> \n> Unless Mercurial does 3-way merge of \"new\", \"theirs\" and \"base\"...\n> with transaction based atomicity (saving \"new\" before attempting\n> merge) they can do that.\n\nI've not read the code, but surely Mercurial does a three-way merge here.\nIt wouldn't be sane to do anything else.\n\n>>> What you use uncomitted changes for, I would use is a separate branch,\n>>> and keep it rebasing (something like using 'mq' in Mercurial).\n>> \n>> Yes, but, as I mentioned, rebasing is less flexible.  A rebase here is\n>> effectively a merge and a commit in one step, whereas my approach separates\n>> the merge and the commit.\n> \n> Errr... what?  You first commit your changes, then keep it rebasing to\n> keep them up to date on top of fresh version.\n\nLike I said before, with my approach, after I merge, I can check that\neverything still compiles, that unit tests still pass, and so on, before\nfinally checking in.  Rebasing, on the other hand, is essentially merging\nand checking in in one step.  *After* you've rebased, you can run unit\ntests, etc., but you've *already* checked in at that point.  (Sure, you\ncould then mutate history if need be, but it's rather less flexible than my\napproach, where the check-in is not made until desired.)\n\n>>> What do you use anonymous branching for?\n>> \n>> Anonymous branching is great for minor divergence that isn't really\n>> significant enough to deserve a name.  It's also great for branches that\n>> *are* significant enough to deserve a name, but where you want to defer\n>> naming the branch right up until you merge it into another branch.  At that\n>> point you can 'name' the branch in the commit message.\n> \n> I think you can use detached HEAD for that, at least when working on\n> one issue at a time (you have to name branch when switching to some\n> other work).\n\nBut in Mercurial I can switch between anonymous branches as much as I like\nwithout anything ever being deleted.\n\n>> From what I read, detached heads are subject to garbage collection.\n>  \n> No, HEAD is protected against garbage collecting.  To be sure you\n> should name a branch when switching branches, though reflog would\n> protect you for 30 days (by default) even if you don't do that.\n\nSo Git doesn't really support anonymous branching as part of a normal\nworkflow.\n"},{"id":"176182","messageId":"20110926003447.GG10955@localhost.localdomain","threadId":"28469","inReplyTo":"1ttmqsxtaj98i$.hv6s5shjeugr.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Konstantin Khomoutov","fromEmail":"flatworm@users.sourceforge.net","sentAt":"2011-09-26T00:34:47Z","receivedAt":"2011-09-26T00:34:47Z","isPatch":false,"sender":{"key":"flatworm@users.sourceforge.net","avatar":null},"body":"On Sun, Sep 25, 2011 at 10:07:24PM +0100, tactical wrote:\n\n[...]\n> > I think you can use detached HEAD for that, at least when working on\n> > one issue at a time (you have to name branch when switching to some\n> > other work).\n> \n> But in Mercurial I can switch between anonymous branches as much as I like\n> without anything ever being deleted.\n> \n> >> From what I read, detached heads are subject to garbage collection.\n> >  \n> > No, HEAD is protected against garbage collecting.  To be sure you\n> > should name a branch when switching branches, though reflog would\n> > protect you for 30 days (by default) even if you don't do that.\n> \n> So Git doesn't really support anonymous branching as part of a normal\n> workflow.\n\nI perceive a certain logical fallacy here: you cannot switch between\nanything anonymous because to switch, you should somehow identify\nsomething to switch to--a name in whatever sense we put into this word.\nAs I understand, by switching between branches in Mercurial you mean\nswitching between directories with clones; if so, you had had to name\nthose directories when they were created.\n\nAs to branches, they do have names in Git but they are very loosely\ncoupled with their names: tag a tip of some branch (to still have a\nhandle on that tip commit) then delete that branch--there will be no\ntraces of that branch's name left, the branch's name is not encoded in\nits history in any way.  The branch names is just a way to not mess with\nSHA-1 names of commits (and to have references to those commits to keep\nthem out of consideration for garbage collection).\nHence the idea to demand support for anonymous branches in Git's model\nis just unfounded.\n"},{"id":"176183","messageId":"1aec7c1qq0n56.sxybjnsj6ngr$.dlg@40tude.net","threadId":"28469","inReplyTo":"20110926003447.GG10955@localhost.localdomain","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-26T00:56:38Z","receivedAt":"2011-09-26T00:56:38Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Konstantin Khomoutov wrote:\n\n>>>> From what I read, detached heads are subject to garbage collection.\n>>>  \n>>> No, HEAD is protected against garbage collecting.  To be sure you\n>>> should name a branch when switching branches, though reflog would\n>>> protect you for 30 days (by default) even if you don't do that.\n>> \n>> So Git doesn't really support anonymous branching as part of a normal\n>> workflow.\n> \n> I perceive a certain logical fallacy here: you cannot switch between\n> anything anonymous because to switch, you should somehow identify\n> something to switch to--a name in whatever sense we put into this word.\n\nIn Mercurial, you can just update to a particular changeset (and you\nidentify that changeset by repository-local revision number or globally\nunique ID) and then commit again.  The point is that there's no need to\ngive a label to a head in Mercurial (although you can if you want to, using\nMercurial bookmarks, which are basically the same as what Git uses).\n\nHere's an example of anonymous branching:\n\n    c:\\test>hg init\n\n    c:\\test>echo test>foo\n\n    c:\\test>hg commit --addremove -m initial\n    adding foo\n\n    c:\\test>echo first>>foo\n\n    c:\\test>hg commit -m first\n\n    c:\\test>hg log\n    changeset:   1:3e895ec28d6c\n    tag:         tip\n    user:        tactical\n    date:        Mon Sep 26 01:39:46 2011 +0100\n    summary:     first\n\n    changeset:   0:b51644bb3450\n    user:        tactical\n    date:        Mon Sep 26 01:39:40 2011 +0100\n    summary:     initial\n\n    c:\\test>hg update 0\n    1 files updated, 0 files merged, 0 files removed, 0 files unresolved\n\n    c:\\test>echo second>>foo\n\n    c:\\test>hg commit -m second\n    created new head\n\n    c:\\test>hg glog\n    @  changeset:   2:35c82a7e7de1\n    |  tag:         tip\n    |  parent:      0:b51644bb3450\n    |  user:        tactical\n    |  date:        Mon Sep 26 01:40:10 2011 +0100\n    |  summary:     second\n    |\n    | o  changeset:   1:3e895ec28d6c\n    |/   user:        tactical\n    |    date:        Mon Sep 26 01:39:46 2011 +0100\n    |    summary:     first\n    |\n    o  changeset:   0:b51644bb3450\n       user:        tactical\n       date:        Mon Sep 26 01:39:40 2011 +0100\n       summary:     initial\n\nI now have two anonymous branches, and these will never be garbage\ncollected.  I can easily update to either branch with \"hg update 1\" or \"hg\nupdate 2\" (or \"hg update 0\" again, if i want to create yet another\nanonymous branch).\n\n> As I understand, by switching between branches in Mercurial you mean\n> switching between directories with clones;\n\nNo.  Clones are a different topic.\n\n> As to branches, they do have names in Git but they are very loosely\n> coupled with their names: tag a tip of some branch (to still have a\n> handle on that tip commit) then delete that branch--there will be no\n> traces of that branch's name left, the branch's name is not encoded in\n> its history in any way.\n\nGit branch names are basically the same as Mercurial bookmarks.  The\ndifference is that in Mercurial you don't *have* to use bookmarks.\n\n> The branch names is just a way to not mess with\n> SHA-1 names of commits (and to have references to those commits to keep\n> them out of consideration for garbage collection).\n> Hence the idea to demand support for anonymous branches in Git's model\n> is just unfounded.\n\nI think it's simply a weakness of Git.  There are zero problems with\nanonymous branching in Mercurial, and it's a very powerful and simple\nsystem.\n"},{"id":"176184","messageId":"CAH5451nk9FnqwhEe0SWxDc3TnLiTLnFgD6zB3jDehFZn6=qWvw@mail.gmail.com","threadId":"28469","inReplyTo":"1aec7c1qq0n56.sxybjnsj6ngr$.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Andrew Ardill","fromEmail":"andrew.ardill@gmail.com","sentAt":"2011-09-26T01:34:04Z","receivedAt":"2011-09-26T01:34:04Z","isPatch":false,"sender":{"key":"andrew.ardill@gmail.com","avatar":"https://gravatar.com/avatar/da14cb7c091dd44dc6c63a4d3361b149acaf25226dc78eb4131a17b93d9b0993?d=mp&s=160"},"body":"On 26 September 2011 10:56, tactical <a5158017@nepwk.com> wrote:\n> Konstantin Khomoutov wrote:\n>\n>>>>> From what I read, detached heads are subject to garbage collection.\n>>>>\n>>>> No, HEAD is protected against garbage collecting.  To be sure you\n>>>> should name a branch when switching branches, though reflog would\n>>>> protect you for 30 days (by default) even if you don't do that.\n>>>\n>>> So Git doesn't really support anonymous branching as part of a normal\n>>> workflow.\n>>\n>> I perceive a certain logical fallacy here: you cannot switch between\n>> anything anonymous because to switch, you should somehow identify\n>> something to switch to--a name in whatever sense we put into this word.\n>\n> In Mercurial, you can just update to a particular changeset (and you\n> identify that changeset by repository-local revision number or globally\n> unique ID) and then commit again.  The point is that there's no need to\n> give a label to a head in Mercurial (although you can if you want to, using\n> Mercurial bookmarks, which are basically the same as what Git uses).\n>\n> Here's an example of anonymous branching:\n>\n>    c:\\test>hg init\n>\n>    c:\\test>echo test>foo\n>\n>    c:\\test>hg commit --addremove -m initial\n>    adding foo\n>\n>    c:\\test>echo first>>foo\n>\n>    c:\\test>hg commit -m first\n>\n>    c:\\test>hg log\n>    changeset:   1:3e895ec28d6c\n>    tag:         tip\n>    user:        tactical\n>    date:        Mon Sep 26 01:39:46 2011 +0100\n>    summary:     first\n>\n>    changeset:   0:b51644bb3450\n>    user:        tactical\n>    date:        Mon Sep 26 01:39:40 2011 +0100\n>    summary:     initial\n>\n>    c:\\test>hg update 0\n>    1 files updated, 0 files merged, 0 files removed, 0 files unresolved\n>\n>    c:\\test>echo second>>foo\n>\n>    c:\\test>hg commit -m second\n>    created new head\n>\n>    c:\\test>hg glog\n>    @  changeset:   2:35c82a7e7de1\n>    |  tag:         tip\n>    |  parent:      0:b51644bb3450\n>    |  user:        tactical\n>    |  date:        Mon Sep 26 01:40:10 2011 +0100\n>    |  summary:     second\n>    |\n>    | o  changeset:   1:3e895ec28d6c\n>    |/   user:        tactical\n>    |    date:        Mon Sep 26 01:39:46 2011 +0100\n>    |    summary:     first\n>    |\n>    o  changeset:   0:b51644bb3450\n>       user:        tactical\n>       date:        Mon Sep 26 01:39:40 2011 +0100\n>       summary:     initial\n>\n> I now have two anonymous branches, and these will never be garbage\n> collected.  I can easily update to either branch with \"hg update 1\" or \"hg\n> update 2\" (or \"hg update 0\" again, if i want to create yet another\n> anonymous branch).\n>\n>> As I understand, by switching between branches in Mercurial you mean\n>> switching between directories with clones;\n>\n> No.  Clones are a different topic.\n>\n>> As to branches, they do have names in Git but they are very loosely\n>> coupled with their names: tag a tip of some branch (to still have a\n>> handle on that tip commit) then delete that branch--there will be no\n>> traces of that branch's name left, the branch's name is not encoded in\n>> its history in any way.\n>\n> Git branch names are basically the same as Mercurial bookmarks.  The\n> difference is that in Mercurial you don't *have* to use bookmarks.\n>\n>> The branch names is just a way to not mess with\n>> SHA-1 names of commits (and to have references to those commits to keep\n>> them out of consideration for garbage collection).\n>> Hence the idea to demand support for anonymous branches in Git's model\n>> is just unfounded.\n>\n> I think it's simply a weakness of Git.  There are zero problems with\n> anonymous branching in Mercurial, and it's a very powerful and simple\n> system.\n>\n\nI am no expert on this, however git can (of course) do 'anonymous\nbranching' just as simply as mercurial, with one caveat; for most\nintents and purposes (as far as I have seen/heard discussed) git and\nmercurial are homomorphic, and in the situations they are not git is\nthe more general system.\n\nThe flow that you are using for anonymous branching in mercurial is\neasily reproducible in git, using detached heads. Checkout a revision\n(note: not a ref)\n  git checkout HEAD@{1}\nhack + commit. Repeat as often as you like. Your concern is that these\nwill (eventually) be garbage collected. Again, I am not an expert in\nthis so please correct me if I have this incorrect, but the man page\nfor gc says:\n\n       git-gc tries very hard to be safe about the garbage it collects. In\n       particular, it will keep not only objects referenced by your current\n       set of branches and tags, but also objects referenced by the index,\n       remote tracking branches, refs saved by git-filter-branch in\n       refs/original/, or reflogs (which may references commits in branches\n       that were later amended or rewound).\n\nAs any commits you make in a detached state are in the reflog until\nthey expire (by default 30 days I think?) you have more than enough\ntime to decide if you want to keep the work - which you can do very\neasily by assigning it a name. If the default time is not long enough,\nsimply extend it in your config\n  git config gc.reflogExpire = 10000 years <- syntax might not be correct\nThe reason this is not true by default is that _most_ people don't\nwork exclusively in anonymous branches, and it is far nicer\nperformance wise to have git clean up for you.\n\nSo you don't *have* to use branches in git - they just make it much\neasier to get around. They cost practically nothing to use, so I don't\nreally understand why you wouldn't want to for anything other than\njust a quick throwaway test or scratch idea.\n\nI hope that clears it up a little.\n\nAndrew\n"},{"id":"176185","messageId":"ejxl2szn9dmh.olc9b5j8rv4h.dlg@40tude.net","threadId":"28469","inReplyTo":"CAH5451nk9FnqwhEe0SWxDc3TnLiTLnFgD6zB3jDehFZn6=qWvw@mail.gmail.com","subject":"Re: More Beginning Git Questions","fromName":"tactical","fromEmail":"a5158017@nepwk.com","sentAt":"2011-09-26T01:42:00Z","receivedAt":"2011-09-26T01:42:00Z","isPatch":false,"sender":{"key":"a5158017@nepwk.com","avatar":null},"body":"Andrew Ardill wrote:\n\n> As any commits you make in a detached state are in the reflog until\n> they expire (by default 30 days I think?) you have more than enough\n> time to decide if you want to keep the work - which you can do very\n> easily by assigning it a name. If the default time is not long enough,\n> simply extend it in your config\n>   git config gc.reflogExpire = 10000 years <- syntax might not be correct\n\nThanks for your post, but, again, my point is that Git does not support\nanonymous branching as part of a normal workflow.  Having X days until\ndetonation is hardly part of a normal workflow (even if X can be changed,\nas you suggest).\n\nAnyway, this thread's really going off topic, so I'll try not to reply\nagain.\n"},{"id":"176238","messageId":"m37h4vp4f0.fsf@localhost.localdomain","threadId":"28469","inReplyTo":"1aec7c1qq0n56.sxybjnsj6ngr$.dlg@40tude.net","subject":"Re: More Beginning Git Questions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-09-26T18:03:59Z","receivedAt":"2011-09-26T18:03:59Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"tactical <a5158017@nepwk.com> writes:\n> Konstantin Khomoutov wrote:\n> \n>>>>> From what I read, detached heads are subject to garbage collection.\n>>>>  \n>>>> No, HEAD is protected against garbage collecting.  To be sure you\n>>>> should name a branch when switching branches, though reflog would\n>>>> protect you for 30 days (by default) even if you don't do that.\n>>> \n>>> So Git doesn't really support anonymous branching as part of a normal\n>>> workflow.\n>> \n>> I perceive a certain logical fallacy here: you cannot switch between\n>> anything anonymous because to switch, you should somehow identify\n>> something to switch to--a name in whatever sense we put into this word.\n> \n> In Mercurial, you can just update to a particular changeset (and you\n> identify that changeset by repository-local revision number or globally\n> unique ID) and then commit again.  The point is that there's no need to\n> give a label to a head in Mercurial (although you can if you want to, using\n> Mercurial bookmarks, which are basically the same as what Git uses).\n> \n> Here's an example of anonymous branching:\n> \n>     c:\\test>hg init\n> \n>     c:\\test>echo test>foo\n> \n>     c:\\test>hg commit --addremove -m initial\n>     adding foo\n> \n>     c:\\test>echo first>>foo\n> \n>     c:\\test>hg commit -m first\n> \n>     c:\\test>hg log\n>     changeset:   1:3e895ec28d6c\n>     tag:         tip\n>     user:        tactical\n>     date:        Mon Sep 26 01:39:46 2011 +0100\n>     summary:     first\n> \n>     changeset:   0:b51644bb3450\n>     user:        tactical\n>     date:        Mon Sep 26 01:39:40 2011 +0100\n>     summary:     initial\n> \n>     c:\\test>hg update 0\n>     1 files updated, 0 files merged, 0 files removed, 0 files unresolved\n> \n>     c:\\test>echo second>>foo\n> \n>     c:\\test>hg commit -m second\n>     created new head\n> \n>     c:\\test>hg glog\n>     @  changeset:   2:35c82a7e7de1\n>     |  tag:         tip\n>     |  parent:      0:b51644bb3450\n>     |  user:        tactical\n>     |  date:        Mon Sep 26 01:40:10 2011 +0100\n>     |  summary:     second\n>     |\n>     | o  changeset:   1:3e895ec28d6c\n>     |/   user:        tactical\n>     |    date:        Mon Sep 26 01:39:46 2011 +0100\n>     |    summary:     first\n>     |\n>     o  changeset:   0:b51644bb3450\n>        user:        tactical\n>        date:        Mon Sep 26 01:39:40 2011 +0100\n>        summary:     initial\n> \n> I now have two anonymous branches, and these will never be garbage\n> collected.  I can easily update to either branch with \"hg update 1\" or \"hg\n> update 2\" (or \"hg update 0\" again, if i want to create yet another\n> anonymous branch).\n\nIn my opinion the need to examine either log ('hg glog') or heads\n('hg heads'?) to see how to switch to anonymous branch is a PITA\nthat far outweights the need to name branches (to give a temporary,\nlocal-only branch name) in Git.\n \nNb. by using \"detached HEAD\" for anonymous branch I meant the\nfollowing:\n\n  $ git checkout --detach\n  $ ...\n  $ <work on detached head>\n\n  worth saving?\n\n  Y. $ git branch -b t foo/temp\n     $ git checkout <other branch>\n    \n  N. $ git checkout <other branch>\n\n> > The branch names is just a way to not mess with\n> > SHA-1 names of commits (and to have references to those commits to keep\n> > them out of consideration for garbage collection).\n> > Hence the idea to demand support for anonymous branches in Git's model\n> > is just unfounded.\n> \n> I think it's simply a weakness of Git.  There are zero problems with\n> anonymous branching in Mercurial, and it's a very powerful and simple\n> system.\n \nIMVVVHO it is just remains of bad initial design decision of Mercurial\nabout representing branches ;-PPPPPPP\n\nOnly now Mercurial has something (transferable bookmarks) which\napproaches flexibility and usability of Git branches.  It took them\nhow long... and even then there is a [supposedly] user-friendly but\nflexibility-reducing notion that branch (bookmark) names are global.\n\n\nNot that Git didn't and doesn't have its share of bad design decisions\n(like autimatically committing a merge).\n\n-- \nJakub Narębski\n"}]}