{"thread":{"id":"11467","subject":"git-pull several branches merge conflict resolved","startedAt":"2008-01-04T09:03:22Z","lastAt":"2008-01-04T09:03:22Z","messageCount":1,"participants":["Cyrill Gorcunov"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"64428","messageId":"20080104090322.GD6310@cvg","threadId":"11467","inReplyTo":null,"subject":"git-pull several branches merge conflict resolved","fromName":"Cyrill Gorcunov","fromEmail":"gorcunov@gmail.com","sentAt":"2008-01-04T09:03:22Z","receivedAt":"2008-01-04T09:03:22Z","isPatch":false,"sender":{"key":"gorcunov@gmail.com","avatar":"https://gravatar.com/avatar/b9d3eb8ea4efbd95564cedde5bf279ef8f36091cf61fac090c8cb75cc4ad6f8b?d=mp&s=160"},"body":"this message is just an attempt to summarize a problem and its decision\ngraciously explained by Junio C Hamano in hope it would help someone else\nwho trip on the same problem\n\nlets start ;)\n\n\n--- the problem ---\n\ni'm keeping Linus's kernel git tree on my local harddrive so i update it from time to\ntime using git-pull command with explicitly defined URL:\n\n\tgit-pull git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nfor some reasons i wish to track changes from Ingo's repository so i made a special\nbranch for it\n\n\tgit-checkout -b x86\n\nthis branch i'm trying to keep up to date with\n\n\tgit-pull --force git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git mm\n\nafter some point (as only Linus has his tree updated) i could not update Ingo's branch\nwithout merge conflicts\n\nso Junio explained what is going on there\n\n\n--- the decision ---\n\nHere is what is happening.\n\n (0) Ingo has this:\n\n                      A---B (== I)\n                     /\n    ----o---o---o---L\n\n     where L is the tip of Linus at some point, I is his changes\n     for x86.  You pull and get the same thing.  Your local x86\n     tip points at commit B.\n\n (1) Then Linus advances and Ingo rebases.  Updated Linus's tip\n     is at L' and Ingo has old patches rebased (A' and B') while\n     he added more changes (C and D).  His tip is at I'.\n\n                      A---B (==I) A'--B'--C---D (==I')\n                     /           /\n    ----o---o---o---L---o---o---L'\n\n (2) You pull.  What is involved is:\n\n     * git-pull is just \"git fetch\" followed by \"git merge\", and\n       in your repository \"git fetch\" can be configured to use a\n       remote tracking branch to keep track of Ingo's progress\n       (but I suspect you don't).  Your \"git branch\" output\n       shows your local branches, and \"git branch -r\" would show\n       these remote tracking branches.\n\n     * The remote tracking is typically configured in\n       .git/config and would look like this:\n\n        [remote \"mingo\"]\n        url = git://git.kernel.org/pub/...\n        fetch = refs/heads/*:refs/remotes/mingo/*\n\n        Although I _suspect_ you do not have it (your $ipull\n        script pulls with explicit URL without using configured\n        information).\n\n     The above (for normal people who have the tracking set up)\n     fetches the branch tip's from Ingo, and store them in\n     corresponding places in .git/refs/remotes/mingo/;  his 'mm'\n     branch will be stored in .git/refs/remotes/mingo/mm.\n\n     But remote.mingo.fetch configuration above does not start\n     with '+' (e.g. \"+refs/heads/*:refs/remotes/mingo/*\", which\n     means \"do allow non-fast-forward\").  For people with such\n     configuration, \"git pull\" from him will fail because\n     remotes/mingo/mm points at commit B before you initiated\n     the fetch and now it points at D which is _NOT_ a\n     descendant of B.\n\n     His recommendation about --force applies _ONLY_ to override\n     this, and allow your remote tracking branch that used to\n     point at B to be replaced to point at D.  I suspect it does\n     not even apply to you as I do not think you are using\n     remote tracking branch at all.\n\n     In any case, once \"git fetch\" completes, \"git merge\"\n     happens.  --force does not affect this step at all.\n\n     What's merged?\n\n     Your 'x86' branch is still at B and you try to merge D into\n     it.\n\n                            .-------------------*\n                           /                   / \n                      A---B       A'--B'--C---D\n                     /           /\n    ----o---o---o---L---o---o---L'\n\n     Because Ingo's tree was rebased, the resulting merge wants\n     to have both versions of A and B (the original and the\n     rebased).  As corresponding patches (say A and A') would\n     want to touch same parts of the code, and Ingo may have\n     improved the latter while all of this has been happening\n     (i.e. A and A' may not be literal rebase but can do things\n     differently), it will inevitably conflict with each other.\n\nEven though the conflict resolution would be trivial (you would\nbasically want to pick what's from A' over A), this is not what\nyou would typically want to happen.  When dealing with a\nrebasing upstream, you often do not want to merge but instead\nrebase yourself.\n\nSo backing up a bit, here is how people would follow rebasing\nupstream:\n\n (0) Ingo has this:\n\n                      A---B (== I)\n                     /\n    ----o---o---o---L\n\n     where L is the tip of Linus at some point, I is his changes\n     for x86.  You pull and get the same thing.  Your local x86\n     tip points at commit B.\n\n (1) You develop on top of Ingo (although you hinted in your\n     description that you are strictly following, that is just a\n     degenerated case of this where (X,Y,Z) is empty in this\n     picture):\n\n                            X---Y---Z\n                           /\n                      A---B (== I)\n                     /\n    ----o---o---o---L\n\n (2) Then Linus advances and Ingo rebases.  Updated Linus's tip\n     is at L' and Ingo has old patches rebased (A' and B') while\n     he added more changes (C and D).  His tip is at I'.\n\n                      A---B (==I) A'--B'--C---D (==I')\n                     /           /\n    ----o---o---o---L---o---o---L'\n\n (3) You do not pull but instead fetch from Ingo to get what\n     happened outside your tree.\n\n                            X---Y---Z\n                           /\n                      A---B (==I) A'--B'--C---D (==I')\n                     /           /\n    ----o---o---o---L---o---o---L'\n\n    Note that your 'x86' is at Z and Ingo's tip is now at D.\n\n (4) You rebase on top of Ingo's updated tip.\n\n                                                X'--Y'--Z'\n                                               /\n                      A---B (==I) A'--B'--C---D (==I')\n                     /           /\n    ----o---o---o---L---o---o---L'\n\n\nI was told that our user manual is very good these days covering\nboth workflows based on merges and workflows based on rebases.\nYou may want to check it and also git-rebase(1).\n\n--- end ---\n\nThanks you very much, Junio!\n\n\t\t- Cyrill -\n"}]}