{"thread":{"id":"20040","subject":"request for documentation about branch surgery","startedAt":"2009-07-06T23:05:12Z","lastAt":"2009-07-07T18:28:57Z","messageCount":10,"participants":["Bruno Haible","Elijah Newren","Junio C Hamano","Andreas Ericsson","Daniel Barkalow"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"117525","messageId":"200907070105.12821.bruno@clisp.org","threadId":"20040","inReplyTo":null,"subject":"request for documentation about branch surgery","fromName":"Bruno Haible","fromEmail":"bruno@clisp.org","sentAt":"2009-07-06T23:05:12Z","receivedAt":"2009-07-06T23:05:12Z","isPatch":false,"sender":{"key":"bruno@clisp.org","avatar":null},"body":"Hi,\n\nHere are a few things that I would have expected to find in the Git user's\nmanual, chapter \"Rewriting history and maintaining patch series\"\n  <http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#cleaning-up-history>\n\nIt is meant for a user who does not yet know about \"git rebase\", \"git merge\",\n\"git reset\" and the like. Organized by the goal that a user has (\"how do I?\").\n\n\n1) After the section \"Rewriting a single commit\", it may be useful to\nhave a section \"Inserting one or more new commits\". This is something that\ncannot be done with the \"detached head\" technique. I found this sequence\nof commands useful:\n\n  If you want to add a commit in the middle of a branch:\n\n            A---C---...---Z    master\n\n  =>\n\n            A---B---C---...---Z    master\n\n  it is achieved by\n\n    $ git checkout A\n    $ git branch temp\n    $ git checkout temp\n    [make changes for B]\n    $ git commit -a\n\n  now:\n\n            A---C---...---Z    master\n             \\\n              --B              temp\n\n    $ git checkout master\n    $ git rebase temp\n    $ git branch -d temp\n\n\n2) About the section \"Reordering or selecting from a patch series\".\n   The \"git rebase\" documentation contains a good example:\n\n   Reordering, possibly merging, the last 5 commits:\n   $ git rebase -i HEAD~5\n   See \"man git-rebase\" under \"INTERACTIVE MODE\".\n\n   I find this technique very useful, because it guarantees that no\n   commit gets lost (unlike \"git cherry-pick\"). Maybe the section could\n   be split into two sections\n      \"Reordering a patch series\"\n   and\n      \"Selecting from a patch series\"?\n\n\n3) When do I need \"git merge\", and when do I need \"git rebase\", in the\n   context of branch surgery?\n\n   The simple answer, that I would find worth mentioning, is:\n     - \"git merge\" copies commits from one branch to another.\n     - \"git rebase\" only moves commits around to make history more linear.\n\n\n4) It would be good to have a section \"Cutting branches\"\n\n   How do I remove the N most recent commits from a branch?\n\n               D---E---F---G---H---.........---Y---Z master\n\n  =>\n               D---E master\n\n   It goes like this:\n\n     $ git checkout master\n     $ git reset --hard E\n\n\n5) Then, it would be good to have a section \"Replacing branches\"\n\n   How do I copy the contents of a branch over to another branch, replacing\n   the recent development on that branch?\n\n  If you want to copy a branch into another, while throwing away commits:\n\n                     F1---F2---F3                         released\n                    /\n               D---E---F---G---H---.........---Y---Z master\n\n  =>\n                     F1---F2---F3   released\n                    /\n               D---E---F1---F2---F3 master\n\n  This is achieved by\n\n    $ git checkout master\n    $ git reset --hard E      # Cut the branch \"master\"\n    $ git merge released      # Copy commits from branch \"released\" to \"master\"\n\n\n6) Also, it would be good to have a section \"Reconnecting branches after rebase\".\n   If you want to reconnect a branch to a rebased master, here's how to do it:\n\n                   /--C'--...---P'--Q'--...---Z'  new rebased master\n              A---B---C---...---P---Q---...---Z   old master\n                                 \\\n                                  --BA---...---BZ  release-branch\n\n  =>\n              A---B---C'--...---P'--Q'--...---Z'  new rebased master\n                                 \\\n                                  --BA---...---BZ  release-branch\n\n  This is achieved by\n\n    $ git checkout release-branch\n    $ git rebase --onto P' P\n\n\nThis might seem exotic, but these use cases all came up while rewriting the\nhistory after a \"git cvsimport\".\n\nBruno\n"},{"id":"117534","messageId":"51419b2c0907061930k71e20b42rb347b9ab8923e437@mail.gmail.com","threadId":"20040","inReplyTo":"200907070105.12821.bruno@clisp.org","subject":"Re: request for documentation about branch surgery","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2009-07-07T02:30:56Z","receivedAt":"2009-07-07T02:30:56Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi,\n\nIt's been a long time since I read the user manual, so I'm only\ncomment to point out a few shortcuts (whether or not they're more\nlogical to present to new users) and clarifications on the usecases\nyou presented.\n\nOn Mon, Jul 6, 2009 at 5:05 PM, Bruno Haible<bruno@clisp.org> wrote:\n> 1) After the section \"Rewriting a single commit\", it may be useful to\n> have a section \"Inserting one or more new commits\". This is something that\n> cannot be done with the \"detached head\" technique. I found this sequence\n> of commands useful:\n>\n>  If you want to add a commit in the middle of a branch:\n>\n>            A---C---...---Z    master\n>\n>  =>\n>\n>            A---B---C---...---Z    master\n>\n>  it is achieved by\n>\n>    $ git checkout A\n>    $ git branch temp\n>    $ git checkout temp\n>    [make changes for B]\n>    $ git commit -a\n>\n>  now:\n>\n>            A---C---...---Z    master\n>             \\\n>              --B              temp\n>\n>    $ git checkout master\n>    $ git rebase temp\n>    $ git branch -d temp\n\nOr compress those 8 steps down to 4 using a detached HEAD and\nmulti-argument rebase:\n  $ git checkout A\n  [make changes for B]\n  $ git commit -a\n  $ git rebase HEAD master\n\nThe last command above means \"rebase master against HEAD\".  I think\nthe rebase command would be much easier to understand for new users if\nit used an \"--against\" before the first reference(*).  For example,\n\"git rebase --against temp\" for rebasing the current branch against\ntemp (instead of \"git rebase temp\") or \"git rebase --against HEAD\nmaster\" (rather than \"git rebase HEAD master\"); the real git rebase\ncommands don't parse so well for new users and take a long time to\nwrap ones' head around, whereas this simple change seems to make it\nmuch easier.\n\n(*) Except when --onto is specified.  Then --since may make more sense\nthan --against.  Also, I'm not yet suggesting we make this change\n(since I have no patch handy), but note that if anyone wants to try\nthis then the \"--against\" should be optional for backwards\ncompatibility.  It's mostly a documentation change.\n\n<snip case 2>\n> 3) When do I need \"git merge\", and when do I need \"git rebase\", in the\n>   context of branch surgery?\n>\n>   The simple answer, that I would find worth mentioning, is:\n>     - \"git merge\" copies commits from one branch to another.\n\ngit merge does not copy commits at all; unlike cvs/svn, a commit may\n(and often is) part of more than one branch in git.  A merge simply\ncreates a new commit which has more than one parent: the previous tip\nof the current branch, and the tip of the other branch you are\nmerging.\n\n>     - \"git rebase\" only moves commits around to make history more linear.\n\ngit rebase actually doesn't move around commits; the old commits still\nexist with no modifications (which is useful for undoing rebases if\nyou later decide you don't like them).  Instead, git rebase just\nre-applies commits, effectively making an extra \"copy\" of each commit\n(I put \"copy\" in quotes because the \"copied\" commits will have\ndifferent parents, different commit times, and potentially different\ncontents especially when conflict resolution is necessary, so they're\nnot quite copies).\n\n> 4) It would be good to have a section \"Cutting branches\"\n>\n>   How do I remove the N most recent commits from a branch?\n>\n>               D---E---F---G---H---.........---Y---Z master\n>\n>  =>\n>               D---E master\n>\n>   It goes like this:\n>\n>     $ git checkout master\n>     $ git reset --hard E\n\nIf master is the active branch, you only need the latter command.  If\nmaster is not the active branch, then you can achieve the same with\nmuch less cost by\n  $ git branch -f master E\n\n> 5) Then, it would be good to have a section \"Replacing branches\"\n>\n>   How do I copy the contents of a branch over to another branch, replacing\n>   the recent development on that branch?\n>\n>  If you want to copy a branch into another, while throwing away commits:\n>\n>                     F1---F2---F3                         released\n>                    /\n>               D---E---F---G---H---.........---Y---Z master\n>\n>  =>\n>                     F1---F2---F3   released\n>                    /\n>               D---E---F1---F2---F3 master\n>\n>  This is achieved by\n>\n>    $ git checkout master\n>    $ git reset --hard E      # Cut the branch \"master\"\n>    $ git merge released      # Copy commits from branch \"released\" to \"master\"\n\nI'm assuming master isn't checked out.  If so, the following is faster:\n  $ git branch -f master E\n\n(If master is checked out, just 'git reset ---hard released')\n\n> 6) Also, it would be good to have a section \"Reconnecting branches after rebase\".\n>   If you want to reconnect a branch to a rebased master, here's how to do it:\n>\n>                   /--C'--...---P'--Q'--...---Z'  new rebased master\n>              A---B---C---...---P---Q---...---Z   old master\n>                                 \\\n>                                  --BA---...---BZ  release-branch\n>\n>  =>\n>              A---B---C'--...---P'--Q'--...---Z'  new rebased master\n>                                 \\\n>                                  --BA---...---BZ  release-branch\n>\n>  This is achieved by\n>\n>    $ git checkout release-branch\n>    $ git rebase --onto P' P\n\nor,\n  $ git rebase --onto P' P release-branch\n\n> This might seem exotic, but these use cases all came up while rewriting the\n> history after a \"git cvsimport\".\n\nThey may seem exotic at first to cvs/svn refugees, but it isn't very\nlong before lots of users end up doing these kinds of things\nroutinely.\n\nAmusing story: I spent several months at $dayjob attempting to\nconvince our group to switch from cvs to git instead of from cvs to\nsvn.  I often mentioned cool features like pulling directly from other\ndevelopers, but was often ignored and laughed off for mentioning\nexotic cases that nearly no one would care about.  And our surveys\nshowed that most developers didn't care about anything other than\n\"checkout, update, and commit\".  I succeeded in the end anyway, and we\nfound out that developers only cared about simple stuff because cvs\nmade anything else painful.  The very first week after switching to\ngit, we had multiple requests from people about how to pull changes\ndirectly from other developers (including from people that previously\nonly cared about \"checkout, update, and commit\").\n\nWhen the cost of certain activities changes dramatically (which git\ndoes by making lots new things possible and fast), formerly \"exotic\"\nusecases can become natural and common -- and really helpful.\n\n\nAnyway, I hope some of my ramblings are useful to you.\n\nElijah\n"},{"id":"117535","messageId":"7vab3hb40x.fsf@alter.siamese.dyndns.org","threadId":"20040","inReplyTo":"200907070105.12821.bruno@clisp.org","subject":"Re: request for documentation about branch surgery","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-07T02:50:06Z","receivedAt":"2009-07-07T02:50:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bruno Haible <bruno@clisp.org> writes:\n\n> 1) After the section \"Rewriting a single commit\", it may be useful to\n> have a section \"Inserting one or more new commits\". This is something that\n> cannot be done with the \"detached head\" technique.\n\nYou learn new things every day, and today is such a day ;-)\n\n>   If you want to add a commit in the middle of a branch:\n>\n>             A---C---...---Z    master\n>\n>   =>\n>\n>             A---B---C---...---Z    master\n>\n>   it is achieved by\n\n        $ git checkout master~25 ;# detach HEAD at A\n        $ edit edit edit\n        $ git commit ;# creates B\n\nwhich makes\n\n               B              HEAD (detached)\n              /\n             A---C---...---Z    master\n\nand then\n\n        $ git rebase HEAD master\n\nwhich reshapes the history into\n\n\n               B---C'--...---Z' master\n              /\n             A---C---...---Z    master@{1}\n\nand you are done.\n\n> 3) When do I need \"git merge\", and when do I need \"git rebase\", in the\n>    context of branch surgery?\n>\n>    The simple answer, that I would find worth mentioning, is:\n>      - \"git merge\" copies commits from one branch to another.\n>      - \"git rebase\" only moves commits around to make history more linear.\n\nIf you think \"git merge\" _copies_, you will never understand what \"merge\"\ndoes.\n\nIf you have master and origin branch, merging them together\n\n                X---Y---Z  origin\n               /\n              /\n             O----A----B master\n\n        $ git checkout master\n        $ git merge origin\n\nwill give you this:\n\n\n                X---Y---Z  origin\n               /         \\\n              /           \\\n             O----A----B---M master\n                       ^\n                       master@{1}\n\nThere is no copying involved anywhere .  It only creates a new commit, M,\nand that commit allows 'master' (that used to point at B) to reach both\nthe history leading to B and the history leading to Z.\n\nOn the other hand, rebase _copies_.  It _does_ make new commits A' and B',\nwhose _effect_ to the tree mimics those of A and B.\n\n        $ git rebase origin master\n\n\n                X---Y---Z---A'---B' master\n               /        ^origin\n              /\n             O----A----B master@{1}\n\n> 4) It would be good to have a section \"Cutting branches\"\n>\n>    How do I remove the N most recent commits from a branch?\n>\n>                D---E---F---G---H---.........---Y---Z master\n>\n>   =>\n>                D---E master\n\nAnd it is not even cutting.  It merely makes this:\n\n                      F---G---H---.........---Y---Z master@{1}\n                     /\n                D---E\n                    ^master\n\nso that a new history can grow at E that is parallel to the\nhistory that leads to Z.\n\nI think your confusion is primarily coming from not understanding what a\nbranch in git is.  A branch in git does not have its own identity per-se,\nand a commit does _not_ belong to a branch, in the sense that a commit\nobject does not record anywhere on which branch it was created on.  A\nbranch is just a pointer into a dag and the pointer can be moved.\n"},{"id":"117536","messageId":"51419b2c0907062045p648d5478x88515261249a2d79@mail.gmail.com","threadId":"20040","inReplyTo":"51419b2c0907061930k71e20b42rb347b9ab8923e437@mail.gmail.com","subject":"Re: request for documentation about branch surgery","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2009-07-07T03:45:22Z","receivedAt":"2009-07-07T03:45:22Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Mon, Jul 6, 2009 at 8:30 PM, Elijah Newren<newren@gmail.com> wrote:\n>>  This is achieved by\n>>\n>>    $ git checkout master\n>>    $ git reset --hard E      # Cut the branch \"master\"\n>>    $ git merge released      # Copy commits from branch \"released\" to \"master\"\n>\n> I'm assuming master isn't checked out.  If so, the following is faster:\n>  $ git branch -f master E\n\nSorry, I meant\n  $ git branch -f master released\nbecause we want to set master to the tip of the released branch, not to E.\n\n> (If master is checked out, just 'git reset ---hard released')\n>\n"},{"id":"117547","messageId":"200907071151.03567.bruno@clisp.org","threadId":"20040","inReplyTo":"51419b2c0907061930k71e20b42rb347b9ab8923e437@mail.gmail.com","subject":"Re: request for documentation about branch surgery","fromName":"Bruno Haible","fromEmail":"bruno@clisp.org","sentAt":"2009-07-07T09:51:02Z","receivedAt":"2009-07-07T09:51:02Z","isPatch":false,"sender":{"key":"bruno@clisp.org","avatar":null},"body":"Hi Elijah,\n\n> When the cost of certain activities changes dramatically (which git\n> does by making lots new things possible and fast), formerly \"exotic\"\n> usecases can become natural and common -- and really helpful.\n\nYes. With cvs, I would not never have dared to do branch surgery. With\ngit, I can - assuming some documentation. \"git clone\", \"git checkout\",\n\"git commit\" each serves a particular purpose, so one can understand\nwhen to use which command. But for branch surgery, several commands\nare available:\n  - \"git reset --hard\"\n  - \"git rebase\"\n  - \"git rebase --onto\"\n  - \"git merge\" (simple case, no merge commit)\nThe mapping from \"How do I ...\" questions to command is not easy,\ntherefore a user's manual like\n  <http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#rewriting-one-commit>\nis needed.\n\nThanks for correcting me and showing simpler alternatives to what\nI said.\n\nStill, can someone please extend the cited chapter of the user's manual,\nso that it answers these questions?\n  - How do I change the last commit in a branch?       [DONE]\n  - How do I change an older commit in a branch?       [DONE]\n  - How do I insert some commits between other commits in a branch?\n                                                       [TODO]\n  - How do I reorder commits in a branch?              [TODO - mention \"git rebase -i\"]\n  - How do I copy selected commits from a branch to another?\n                                                       [DONE]\n  - How do I cut a branch?                             [TODO]\n  - How do I replace a branch tip with the contents of another branch?\n                                                       [TODO]\n  - How do I reconnect a branch to another branch point?\n                                                       [TODO]\n\n> I think\n> the rebase command would be much easier to understand for new users if\n> it used an \"--against\" before the first reference(*).\n\nDon't know, this is just a cosmetic change. The thing that confused me\nabout \"git rebase\" is that its thinking is focused on the current branch.\nWhereas when I'm doing branch surgery, I'm creating a new branch\nbottom-up, so my thinking is \"here I have some commits, what can I do\nwith them\". It requires a good user's manual to map this to the right\n\"git rebase\" command.\n\nBruno\n"},{"id":"117548","messageId":"4A531E30.5040907@op5.se","threadId":"20040","inReplyTo":"200907071151.03567.bruno@clisp.org","subject":"Re: request for documentation about branch surgery","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2009-07-07T10:06:40Z","receivedAt":"2009-07-07T10:06:40Z","isPatch":false,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Bruno Haible wrote:\n> I said.\n> \n> Still, can someone please extend the cited chapter of the user's manual,\n\nPresumably you can. I'll jot down some notes for you though ;-)\n\n> so that it answers these questions?\n>   - How do I insert some commits between other commits in a branch?\n>                                                        [TODO]\n\ngit rebase --interactive (don't do this on published branches).\n\n>   - How do I reorder commits in a branch?              [TODO - mention \"git rebase -i\"]\n\ngit rebase --interactive\n\n>   - How do I cut a branch?                             [TODO]\n\nDefine \"cut\". Possibly \"git branch -d\" or it's less forgiving\nsibling \"git branch -D\", in case the branch to be removed isn't\nfully merged.\n\n>   - How do I replace a branch tip with the contents of another branch?\n>                                                        [TODO]\n\nEasily understandable:\ngit checkout branch\ngit reset --hard otherbranch\n\nThe low-level way:\ngit update-ref [-m <reason>] [--no-deref] <full-ref-name> <newvalue>\n\nThere are more options to git-update-ref. The man-page lists them all.\n\n>   - How do I reconnect a branch to another branch point?\n>                                                        [TODO]\n\nI don't quite understand what you mean by \"reconnect\", but this might\ndo something along the lines of what you want:\ngit checkout branch-to-connect-to\ngit merge branch-to-be-connected\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n\nConsidering the successes of the wars on alcohol, poverty, drugs and\nterror, I think we should give some serious thought to declaring war\non peace.\n"},{"id":"117549","messageId":"200907071213.25418.bruno@clisp.org","threadId":"20040","inReplyTo":"7vab3hb40x.fsf@alter.siamese.dyndns.org","subject":"Re: request for documentation about branch surgery","fromName":"Bruno Haible","fromEmail":"bruno@clisp.org","sentAt":"2009-07-07T10:13:24Z","receivedAt":"2009-07-07T10:13:24Z","isPatch":false,"sender":{"key":"bruno@clisp.org","avatar":null},"body":"Hi Junio,\n\n> You learn new things every day, and today is such a day ;-)\n> \n> >   If you want to add a commit in the middle of a branch:\n> >\n> >             A---C---...---Z    master\n> >\n> >   =>\n> >\n> >             A---B---C---...---Z    master\n> >\n> >   it is achieved by\n> \n>         $ git checkout master~25 ;# detach HEAD at A\n>         $ edit edit edit\n>         $ git commit ;# creates B\n> \n> which makes\n> \n>                B              HEAD (detached)\n>               /\n>              A---C---...---Z    master\n> \n> and then\n> \n>         $ git rebase HEAD master\n> \n> which reshapes the history into\n> \n> \n>                B---C'--...---Z' master\n>               /\n>              A---C---...---Z    master@{1}\n> \n> and you are done.\n\nCool! I wouldn't have guessed that. Now you wrote it into the mailing list\narchives. It would be even better if it were mentioned in the user's manual,\nchapter \"Rewriting history and maintaining patch series\"\n\n> > 3) When do I need \"git merge\", and when do I need \"git rebase\", in the\n> >    context of branch surgery?\n> >\n> >    The simple answer, that I would find worth mentioning, is:\n> >      - \"git merge\" copies commits from one branch to another.\n> >      - \"git rebase\" only moves commits around to make history more linear.\n> \n> If you think \"git merge\" _copies_, you will never understand what \"merge\"\n> does. ... There is no copying involved anywhere .  It only creates a new\n> commit \n\nThere are two cases of \"git merge\" operation: the one that creates a diamond\ncommit, and the one that doesn't (the \"simple\" case of \"git merge\"). The latter\noperation I found useful in achieving this surgery:\n\n            C---D---E              topic\n           /\n      A---B                        master\n\n  =>\n\n            C---D---E              topic\n           /\n      A---B---C---D---E            master\n\nHow do I do this, if not by using \"git merge\"? Is there a way to do it with\n\"git rebase\" only?\n\nIf I have a certain task at hand, what rule of thumb would you give me,\nwhen can I do it with \"git rebase\", and when can I do it with the simple case\nof \"git merge\"?\n\n> > 4) It would be good to have a section \"Cutting branches\"\n> >\n> >    How do I remove the N most recent commits from a branch?\n> >\n> >                D---E---F---G---H---.........---Y---Z master\n> >\n> >   =>\n> >                D---E master\n> \n> And it is not even cutting.  It merely makes this:\n> \n>                       F---G---H---.........---Y---Z master@{1}\n>                      /\n>                 D---E\n>                     ^master\n\nI regularly use \"git repack -a -d\", so that branches like that\nmaster@{1} get garbage collected. So from the point of view of someone\nwho considers only the contents of the commits that sit on branches,\nit *does* cut the branch.\n\nI know that all commits are still present and reachable by their ID,\nas long as they have not been garbage collected. But when doing\nbranch surgery, only the contents of the labelled branches matters to me.\n\n> I think your confusion is primarily coming from not understanding what a\n> branch in git is.  A branch in git does not have its own identity per-se,\n> and a commit does _not_ belong to a branch, in the sense that a commit\n> object does not record anywhere on which branch it was created on.  A\n> branch is just a pointer into a dag and the pointer can be moved.\n\nOh, I do and did know all this. There is no confusion about that. My problem\nwas that\n  - I had a couple of \"how do I ...\" questions regarding branch surgery,\n  - the mapping between such a task and the git command to use is not clear\n    (combinations of \"git checkout\", \"git branch\", \"git rebase\", \"git merge\",\n    \"git reset\", \"git cherry-pick\" - enough complicated commands to get\n    confused),\n  - the user's manual answered only half of my questions.\n\nBruno\n"},{"id":"117552","messageId":"4A532B9E.7020606@op5.se","threadId":"20040","inReplyTo":"200907071213.25418.bruno@clisp.org","subject":"Re: request for documentation about branch surgery","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2009-07-07T11:03:58Z","receivedAt":"2009-07-07T11:03:58Z","isPatch":false,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Bruno Haible wrote:\n> Hi Junio,\n> \n>> You learn new things every day, and today is such a day ;-)\n>>\n>>>   If you want to add a commit in the middle of a branch:\n>>>\n>>>             A---C---...---Z    master\n>>>\n>>>   =>\n>>>\n>>>             A---B---C---...---Z    master\n>>>\n>>>   it is achieved by\n>>         $ git checkout master~25 ;# detach HEAD at A\n>>         $ edit edit edit\n>>         $ git commit ;# creates B\n>>\n>> which makes\n>>\n>>                B              HEAD (detached)\n>>               /\n>>              A---C---...---Z    master\n>>\n>> and then\n>>\n>>         $ git rebase HEAD master\n>>\n>> which reshapes the history into\n>>\n>>\n>>                B---C'--...---Z' master\n>>               /\n>>              A---C---...---Z    master@{1}\n>>\n>> and you are done.\n> \n> Cool! I wouldn't have guessed that. Now you wrote it into the mailing list\n> archives. It would be even better if it were mentioned in the user's manual,\n> chapter \"Rewriting history and maintaining patch series\"\n> \n\nAnyone can submit patches. I find your persistent urging that someone else\ndo this for you slightly annoying. Now that you've been helped along the\nway to understanding, it's your turn to do your bit and write up the info\nyou've received as a proper patch. This will help ensure that:\na) Other people can find the relevant information quickly\nb) We won't have to answer the same questions again\nc) You gain an even deeper understanding about how the various features\n   actually work as your patches are submitted for review and improvements\n   are suggested for them by the list members\nd) We answer your questions again next time you have any\n\nYou can ofcourse refrain from submitting patches and just hope that d)\nhappens anyway. It probably will, but not indefinitely.\n\nThanks.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n\nConsidering the successes of the wars on alcohol, poverty, drugs and\nterror, I think we should give some serious thought to declaring war\non peace.\n"},{"id":"117567","messageId":"7v3a98bidr.fsf@alter.siamese.dyndns.org","threadId":"20040","inReplyTo":"200907071213.25418.bruno@clisp.org","subject":"Re: request for documentation about branch surgery","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-07T15:52:16Z","receivedAt":"2009-07-07T15:52:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bruno Haible <bruno@clisp.org> writes:\n\n>> If you think \"git merge\" _copies_, you will never understand what \"merge\"\n>> does. ... There is no copying involved anywhere .  It only creates a new\n>> commit \n>\n> There are two cases of \"git merge\" operation: the one that creates a diamond\n> commit, and the one that doesn't (the \"simple\" case of \"git merge\"). The latter\n> operation I found useful in achieving this surgery:\n>\n>             C---D---E              topic\n>            /\n>       A---B                        master\n>\n>   =>\n>\n>             C---D---E              topic\n>            /\n>       A---B---C---D---E            master\n\nIf C, D, E on the above two lines are the _same_ commit, i.e. with the\nsame history and same object IDs, then the picture should instead look\nlike this:\n\n             C---D---E topic\n            /\n       A---B master\n\n   =>\n                       master\n             C---D---E topic\n            /\n       A---B master@{1}\n\nIf that is the case, you drew the picture incorrectly, and it shows the\nmisunderstanding of your git object model and what a git branch is.\n\nThe latter I have already explained to you, but here is a hint.\n\n    Do not think of a branch as \"the upper line is topic, the lower line\n    is master\".  A branch is just a pointer to _a commit_.  IOW, in the\n    picture I drew to correct yours, master and topic point at \"E\".  It\n    does _not_ point at the line that C, D, and E are on.  Similarly,\n    master@{1} points at the commit \"B\", not at the line A and B are on.\n\nYou claimed that you understand in your response, but judging from the way\nyou wrote the above picture, I can tell that you don't understand what a\nbranch in git is.  Otherwise you would have drew it like how I did, and\nyou wouldn't have used the word \"copy\".\n\nIf you instead for some reason _want_ a forked history where C, D and E\nare _duplicated_, then you would start from the first picture, fast\nforward master to \"E\", and would force rebase onto B, to end up with\na picture like this.\n\n             C---D---E topic\n            /\n       A---B---C'--D'--E' master\n\nBut there is no reason to do this.\n"},{"id":"117573","messageId":"alpine.LNX.2.00.0907071400170.2147@iabervon.org","threadId":"20040","inReplyTo":"200907070105.12821.bruno@clisp.org","subject":"Re: request for documentation about branch surgery","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-07-07T18:28:57Z","receivedAt":"2009-07-07T18:28:57Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Tue, 7 Jul 2009, Bruno Haible wrote:\n\n> 6) Also, it would be good to have a section \"Reconnecting branches after rebase\".\n>    If you want to reconnect a branch to a rebased master, here's how to do it:\n> \n>                    /--C'--...---P'--Q'--...---Z'  new rebased master\n>               A---B---C---...---P---Q---...---Z   old master\n>                                  \\\n>                                   --BA---...---BZ  release-branch\n> \n>   =>\n>               A---B---C'--...---P'--Q'--...---Z'  new rebased master\n>                                  \\\n>                                   --BA---...---BZ  release-branch\n\nThis is impossible; the parent of BA is P, not P'.\n\n                   /--C'--...---P'--Q'--...---Z'  new rebased master\n              A---B---C---...---P---Q---...---Z   old master\n                                 \\\n                                  --BA---...---BZ  release-branch\n\n  =>\n                                  --BA'--...---BZ' release branch\n                                 /\n                   /--C'--...---P'--Q'--...---Z'  new rebased master\n              A---B---C---...---P---Q---...---Z\n                                 \\\n                                  --BA---...---BZ\n\nIn order to draw well-formed tree sequences, you can only add items to the \ntrees, and only use each letter once in the whole thing. When you've got a \ncomplete history following those rules, you can elide parts of the history \nthat aren't referenced any more, but you still can't reuse their letters.\n\nYou're drawing some of your trees as if it were possible to have commits \nthat are not eq but are equal; in fact, all information about a commit, \nincluding its parentage, is immutable and contributes to the way it is \nreferenced, so any equal commits are eq (and therefore only appear in one \nspot on the graph).\n\n\t-Daniel\n*This .sig left intentionally blank*\n"}]}