{"thread":{"id":"53819","subject":"rebase - \"fixup!\" conflict applied at the wrong code location, why ?","startedAt":"2020-07-08T23:03:55Z","lastAt":"2020-07-14T05:46:12Z","messageCount":5,"participants":["Philippe Blain","Elijah Newren"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"401202","messageId":"7A30EA48-72E3-47E1-9792-136D7B96DC84@gmail.com","threadId":"53819","inReplyTo":null,"subject":"rebase - \"fixup!\" conflict applied at the wrong code location, why ?","fromName":"Philippe Blain","fromEmail":"levraiphilippeblain@gmail.com","sentAt":"2020-07-08T23:03:44Z","receivedAt":"2020-07-08T23:03:55Z","isPatch":false,"sender":{"key":"levraiphilippeblain@gmail.com","avatar":"https://avatars.githubusercontent.com/u/44212482?v=4"},"body":"Hello,\n\nI've been working on a branch for a while. I've been using `git commit --fixup`  and `git commit --squash`\nwhen I noticed that I had forgotten to add something to a previous commit.\nToday I did `git rebase --autosquash` to clean up my history, and the rebase failed at the\nfirst 'fixup!' commit with a conflict. However, the conflict is not located at the right place \nin the code (it's not in the right subroutine!). This is very surprising to me, and I would \nlike to understand why it happens.\n\nSteps to reproduce:\n\ngit clone -b branch-to-be-rebased https://github.com/phil-blain/CICE.git cice\ncd cice\ngit rebase -i --autosquash my-first-commit\n# save the todo list without modifications\n  Auto-merging <file> \n  CONFLICT (content): Merge conflict in <file>\n  error: could not apply e8bfa55... fixup! <commit message of f4e1ae6>\n# the rebase stops at f4e1ae6\ngit diff\n# tangential question : for some reason the hunk header does not appear here, I don't know why... \ngit diff -2  # but it appears here\ngit grep -p -e '<<<<<<< HEAD' -e '>>>>>>> e8bfa55...'  # or here\n# ok, the conflict appears in subroutine 'picard_solver'\ngit show REBASE_HEAD -U5\n# but the original \"fixup!\" commit only modifies the subroutine 'anderson_solver' !!\n\nI would have expected that the conflict be created around lines 1118-1132 \n(line numbers in f4e1ae6), in the 'anderson_solver' subroutine.\n\nI don't know if this plays a part here, but commit f4e1ae6 (where the rebase stops)\nis the commit where the 'anderson_solver' subroutine is added to the code...\n\nThanks,\n\nPhilippe.\n\n\n"},{"id":"401204","messageId":"C284D053-AD17-4321-88CD-3596F0FAF1AC@gmail.com","threadId":"53819","inReplyTo":"7A30EA48-72E3-47E1-9792-136D7B96DC84@gmail.com","subject":"Re: rebase - \"fixup!\" conflict applied at the wrong code location, why ?","fromName":"Philippe Blain","fromEmail":"levraiphilippeblain@gmail.com","sentAt":"2020-07-08T23:07:05Z","receivedAt":"2020-07-08T23:07:11Z","isPatch":false,"sender":{"key":"levraiphilippeblain@gmail.com","avatar":"https://avatars.githubusercontent.com/u/44212482?v=4"},"body":"\n> Le 8 juil. 2020 à 19:03, Philippe Blain <levraiphilippeblain@gmail.com> a écrit :\n> \n> Steps to reproduce:\n\nForgot to mention that all of this was tested with both Git 2.27.0 and 2.27.0.22.g20514004dd"},{"id":"401228","messageId":"CABPp-BEu=7xSLk5AE8sQX+S-vvYXxgn+avQ8+9ttdSKDjikb9w@mail.gmail.com","threadId":"53819","inReplyTo":"7A30EA48-72E3-47E1-9792-136D7B96DC84@gmail.com","subject":"Re: rebase - \"fixup!\" conflict applied at the wrong code location, why ?","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-07-09T04:07:07Z","receivedAt":"2020-07-09T04:07:21Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Wed, Jul 8, 2020 at 5:07 PM Philippe Blain\n<levraiphilippeblain@gmail.com> wrote:\n>\n> Hello,\n>\n> I've been working on a branch for a while. I've been using `git commit --fixup`  and `git commit --squash`\n> when I noticed that I had forgotten to add something to a previous commit.\n> Today I did `git rebase --autosquash` to clean up my history, and the rebase failed at the\n> first 'fixup!' commit with a conflict. However, the conflict is not located at the right place\n> in the code (it's not in the right subroutine!). This is very surprising to me, and I would\n> like to understand why it happens.\n>\n> Steps to reproduce:\n>\n> git clone -b branch-to-be-rebased https://github.com/phil-blain/CICE.git cice\n> cd cice\n> git rebase -i --autosquash my-first-commit\n> # save the todo list without modifications\n>   Auto-merging <file>\n>   CONFLICT (content): Merge conflict in <file>\n>   error: could not apply e8bfa55... fixup! <commit message of f4e1ae6>\n> # the rebase stops at f4e1ae6\n> git diff\n> # tangential question : for some reason the hunk header does not appear here, I don't know why...\n> git diff -2  # but it appears here\n> git grep -p -e '<<<<<<< HEAD' -e '>>>>>>> e8bfa55...'  # or here\n> # ok, the conflict appears in subroutine 'picard_solver'\n> git show REBASE_HEAD -U5\n> # but the original \"fixup!\" commit only modifies the subroutine 'anderson_solver' !!\n>\n> I would have expected that the conflict be created around lines 1118-1132\n> (line numbers in f4e1ae6), in the 'anderson_solver' subroutine.\n>\n> I don't know if this plays a part here, but commit f4e1ae6 (where the rebase stops)\n> is the commit where the 'anderson_solver' subroutine is added to the code...\n>\n> Thanks,\n>\n> Philippe.\n\nIf you take a look where the rebase stops, you see:\n\n$ git ls-files -u\n100644 ee4377f1ec6836fa05573976a473373906c37d9f 1\ncicecore/cicedynB/dynamics/ice_dyn_vp.F90\n100644 30c699ac371c2a751052fa98d04317e84a96ec47 2\ncicecore/cicedynB/dynamics/ice_dyn_vp.F90\n100644 276f224e9048fe0bbd7c25822695049547362c87 3\ncicecore/cicedynB/dynamics/ice_dyn_vp.F90\n\nThe difference from the merge base to \"other\" (index 3) is pretty\ntiny, you just moved one line in the \"anderson_solver\" subroutine\nabout 10 lines down.  The more interesting difference is from the\nmerge base to \"ours\" (index 2), seen with:\n\n$ git diff :1:cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n:2:cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n\nIf you search for \"anderson_solver\" in that diff, you see that the\nreconstructed diff looks like \"subroutine anderson_solver\" is renamed\nto \"subroutine picard_solver\" with similar but slightly different\narguments.  The diff routine successfully finds lots of lines common\nbetween these two subroutines so it seems quite logical as a way of\nrepresenting the changes, especially since they occur near each other\nin the order of the file.  If you keep looking further in the diff, it\nsays that a few hundred lines later there's another subroutine rename,\nthis time from \"subroutine calc_zeta_Pr\" to \"subroutine\nanderson_solver\".  Looking at it this way, it's quite natural to apply\nthe change from the rebased commit to the picard_solver since the\nother side of history \"renamed\" anderson_solver to picard_solver.\n\nThis might not make as much sense to you, since you tend to think in\nterms of parse trees and \"subroutines\" are a high level unit.  But\ndiffs work in terms of lines and have no knowledge of any kind of file\nstructure or semantics.  If you have a string of functions A,B,C and\ninsert a new function Z on one side of history somewhere in a file\nthat happens to look a lot like existing functions (meaning several\nidentical lines between the two), then diffs won't necessarily treat\nit as a contiguous block of inserted lines but instead compare\nfunction Z on one side to function B on the other, then function B on\nthe first side to function C on the second, etc.\n\nThere are alternative diff algorithms that try to minimize the number\nof changed lines shown by the diff, such as --histogram and\n--patience, and they do shrink this particular diff, but they both\nyield the same treatment of comparing \"subroutine anderson_solver\" to\n\"subroutine picard_solver\" essentially treating it as a rename.  To\nget a merge like you want, you'd need some kind of higher level\nsemantic merge, or at least need functions to not have so many lines\nin common between them.\n\nThis kind of problem also causes big issues when reordering functions\nin a file.  line-by-line diffs and the diff3 merge algorithm tend to\nreally struggle with those.  (See e.g.\nhttps://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf if you want\nto read up more on these.)\n\nHope that helps,\nElijah\n"},{"id":"401527","messageId":"D99E27A0-04BC-40B7-A073-66E1301FFE5D@gmail.com","threadId":"53819","inReplyTo":"CABPp-BEu=7xSLk5AE8sQX+S-vvYXxgn+avQ8+9ttdSKDjikb9w@mail.gmail.com","subject":"Re: rebase - \"fixup!\" conflict applied at the wrong code location, why ?","fromName":"Philippe Blain","fromEmail":"levraiphilippeblain@gmail.com","sentAt":"2020-07-14T02:42:07Z","receivedAt":"2020-07-14T02:42:13Z","isPatch":false,"sender":{"key":"levraiphilippeblain@gmail.com","avatar":"https://avatars.githubusercontent.com/u/44212482?v=4"},"body":"Hi Elijah,\n\n> Le 9 juil. 2020 à 00:07, Elijah Newren <newren@gmail.com> a écrit :\n> \n> On Wed, Jul 8, 2020 at 5:07 PM Philippe Blain\n> <levraiphilippeblain@gmail.com> wrote:\n>> \n>> Hello,\n>> \n>> I've been working on a branch for a while. I've been using `git commit --fixup`  and `git commit --squash`\n>> when I noticed that I had forgotten to add something to a previous commit.\n>> Today I did `git rebase --autosquash` to clean up my history, and the rebase failed at the\n>> first 'fixup!' commit with a conflict. However, the conflict is not located at the right place\n>> in the code (it's not in the right subroutine!). This is very surprising to me, and I would\n>> like to understand why it happens.\n>> \n>> Steps to reproduce:\n>> \n>> git clone -b branch-to-be-rebased https://github.com/phil-blain/CICE.git cice\n>> cd cice\n>> git rebase -i --autosquash my-first-commit\n>> # save the todo list without modifications\n>>  Auto-merging <file>\n>>  CONFLICT (content): Merge conflict in <file>\n>>  error: could not apply e8bfa55... fixup! <commit message of f4e1ae6>\n>> # the rebase stops at f4e1ae6\n>> git diff\n>> # tangential question : for some reason the hunk header does not appear here, I don't know why...\n>> git diff -2  # but it appears here\n>> git grep -p -e '<<<<<<< HEAD' -e '>>>>>>> e8bfa55...'  # or here\n>> # ok, the conflict appears in subroutine 'picard_solver'\n>> git show REBASE_HEAD -U5\n>> # but the original \"fixup!\" commit only modifies the subroutine 'anderson_solver' !!\n>> \n>> I would have expected that the conflict be created around lines 1118-1132\n>> (line numbers in f4e1ae6), in the 'anderson_solver' subroutine.\n>> \n>> I don't know if this plays a part here, but commit f4e1ae6 (where the rebase stops)\n>> is the commit where the 'anderson_solver' subroutine is added to the code...\n>> \n>> Thanks,\n>> \n>> Philippe.\n> \n> If you take a look where the rebase stops, you see:\n\nFirst, thanks a lot for your answer. I have a few questions.\n\n> \n> $ git ls-files -u\n> 100644 ee4377f1ec6836fa05573976a473373906c37d9f 1\n> cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> 100644 30c699ac371c2a751052fa98d04317e84a96ec47 2\n> cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> 100644 276f224e9048fe0bbd7c25822695049547362c87 3\n> cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> \n> The difference from the merge base to \"other\" (index 3) is pretty\n> tiny, you just moved one line in the \"anderson_solver\" subroutine\n> about 10 lines down.  \n\nYes, the output from \n$ git diff :1:cicecore/cicedynB/dynamics/ice_dyn_vp.F90 :3:cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n\nseems to be the same as the one from\n$ git show REBASE_HEAD\n\nThis is a little confusing to me, in the sense that I don't understand why \nthe merge-base is what it is. At this point, I do\n\n$ git merge-base HEAD REBASE_HEAD \nf4e1ae67b7d6ca36c6f3ea7c9da43d81caf24067\n\nOk, so 'git merge-base' finds that the merge-base between HEAD and\nREBASE_HEAD is HEAD; this makes sense to me (no previous commits\nhave been rewritten so far, so REBASE_HEAD is directly ahead of HEAD).\nBut, if I try to find the commit that contains\nthe blob ee4377f1ec6836fa05573976a473373906c37d9f (index 1), I find\nREBASE_HEAD's parent:\n\n$ git log --all --find-object=ee4377f1ec6836fa05573976a473373906c37d9f --format='commmit %H%ntree %T%nparent %P%n%n    %s%n'\ncommmit e8bfa557d3c81b75116d6557784b0439b792a308\ntree f6fecb8193c3b877f22bcb8f4d8d2c203e17f06f\nparent 7a8d5a82984dfedd7fac1d7ed7c7fbd1781c1f61\n\n    fixup! Add Anderson acceleration for Picard iteration\n\ncommmit 7a8d5a82984dfedd7fac1d7ed7c7fbd1781c1f61\ntree 11fd096851015c0c16b793d9bbb5db039776483b\nparent 63d4c73c1dd973f620307833bd363a1d5069d090\n\n    ice_dyn_vp: introduce 'CICE_USE_LAPACK' preprocessor macro\n\n$ blob=ee4377f1ec6836fa05573976a473373906c37d9f\n$ parent=7a8d5a82984dfedd7fac1d7ed7c7fbd1781c1f61\n$ git ls-tree -r $parent^{tree} | grep $blob\n100644 blob ee4377f1ec6836fa05573976a473373906c37d9f\tcicecore/cicedynB/dynamics/ice_dyn_vp.F90\n\nI don't understand why at this point of the rebase, Git \ndetermines that the merge-base between HEAD and \nREBASE_HEAD is REBASE_HEAD's parent... this commit\nis not even an ancestor of HEAD (or maybe I don't understand\nwhat the \"merge-base\" is in this context?)...\n\n> The more interesting difference is from the\n> merge base to \"ours\" (index 2), seen with:\n> \n> $ git diff :1:cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> :2:cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> \n> If you search for \"anderson_solver\" in that diff, you see that the\n> reconstructed diff looks like \"subroutine anderson_solver\" is renamed\n> to \"subroutine picard_solver\" with similar but slightly different\n> arguments.  The diff routine successfully finds lots of lines common\n> between these two subroutines so it seems quite logical as a way of\n> representing the changes, especially since they occur near each other\n> in the order of the file.  If you keep looking further in the diff, it\n> says that a few hundred lines later there's another subroutine rename,\n> this time from \"subroutine calc_zeta_Pr\" to \"subroutine\n> anderson_solver\".  Looking at it this way, it's quite natural to apply\n> the change from the rebased commit to the picard_solver since the\n> other side of history \"renamed\" anderson_solver to picard_solver.\n> \n> This might not make as much sense to you, since you tend to think in\n> terms of parse trees and \"subroutines\" are a high level unit.  But\n> diffs work in terms of lines and have no knowledge of any kind of file\n> structure or semantics.  If you have a string of functions A,B,C and\n> insert a new function Z on one side of history somewhere in a file\n> that happens to look a lot like existing functions (meaning several\n> identical lines between the two), then diffs won't necessarily treat\n> it as a contiguous block of inserted lines but instead compare\n> function Z on one side to function B on the other, then function B on\n> the first side to function C on the second, etc.\n> \n> There are alternative diff algorithms that try to minimize the number\n> of changed lines shown by the diff, such as --histogram and\n> --patience, and they do shrink this particular diff, but they both\n> yield the same treatment of comparing \"subroutine anderson_solver\" to\n> \"subroutine picard_solver\" essentially treating it as a rename.  To\n> get a merge like you want, you'd need some kind of higher level\n> semantic merge, or at least need functions to not have so many lines\n> in common between them.\n\nThanks for these explanations. The behaviour makes sense.\n\n> \n> This kind of problem also causes big issues when reordering functions\n> in a file.  line-by-line diffs and the diff3 merge algorithm tend to\n> really struggle with those.  (See e.g.\n> https://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf if you want\n> to read up more on these.)\n\nThanks for the pointer! \n\n> \n> Hope that helps,\n> Elijah\n\nThanks,\nPhilippe.\n\n"},{"id":"401538","messageId":"CABPp-BGrSYHzf0oLHUPJOz0XQ5sSV-kXxvVAdxjuR2rVsd4oBA@mail.gmail.com","threadId":"53819","inReplyTo":"D99E27A0-04BC-40B7-A073-66E1301FFE5D@gmail.com","subject":"Re: rebase - \"fixup!\" conflict applied at the wrong code location, why ?","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-07-14T05:45:59Z","receivedAt":"2020-07-14T05:46:12Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi Philippe,\n\nOn Mon, Jul 13, 2020 at 8:42 PM Philippe Blain\n<levraiphilippeblain@gmail.com> wrote:\n>\n> Hi Elijah,\n>\n> > Le 9 juil. 2020 à 00:07, Elijah Newren <newren@gmail.com> a écrit :\n> >\n> > On Wed, Jul 8, 2020 at 5:07 PM Philippe Blain\n> > <levraiphilippeblain@gmail.com> wrote:\n> >>\n> >> Hello,\n> >>\n> >> I've been working on a branch for a while. I've been using `git commit --fixup`  and `git commit --squash`\n> >> when I noticed that I had forgotten to add something to a previous commit.\n> >> Today I did `git rebase --autosquash` to clean up my history, and the rebase failed at the\n> >> first 'fixup!' commit with a conflict. However, the conflict is not located at the right place\n> >> in the code (it's not in the right subroutine!). This is very surprising to me, and I would\n> >> like to understand why it happens.\n> >>\n> >> Steps to reproduce:\n> >>\n> >> git clone -b branch-to-be-rebased https://github.com/phil-blain/CICE.git cice\n> >> cd cice\n> >> git rebase -i --autosquash my-first-commit\n> >> # save the todo list without modifications\n> >>  Auto-merging <file>\n> >>  CONFLICT (content): Merge conflict in <file>\n> >>  error: could not apply e8bfa55... fixup! <commit message of f4e1ae6>\n> >> # the rebase stops at f4e1ae6\n> >> git diff\n> >> # tangential question : for some reason the hunk header does not appear here, I don't know why...\n> >> git diff -2  # but it appears here\n> >> git grep -p -e '<<<<<<< HEAD' -e '>>>>>>> e8bfa55...'  # or here\n> >> # ok, the conflict appears in subroutine 'picard_solver'\n> >> git show REBASE_HEAD -U5\n> >> # but the original \"fixup!\" commit only modifies the subroutine 'anderson_solver' !!\n> >>\n> >> I would have expected that the conflict be created around lines 1118-1132\n> >> (line numbers in f4e1ae6), in the 'anderson_solver' subroutine.\n> >>\n> >> I don't know if this plays a part here, but commit f4e1ae6 (where the rebase stops)\n> >> is the commit where the 'anderson_solver' subroutine is added to the code...\n> >>\n> >> Thanks,\n> >>\n> >> Philippe.\n> >\n> > If you take a look where the rebase stops, you see:\n>\n> First, thanks a lot for your answer. I have a few questions.\n>\n> >\n> > $ git ls-files -u\n> > 100644 ee4377f1ec6836fa05573976a473373906c37d9f 1\n> > cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> > 100644 30c699ac371c2a751052fa98d04317e84a96ec47 2\n> > cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> > 100644 276f224e9048fe0bbd7c25822695049547362c87 3\n> > cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n> >\n> > The difference from the merge base to \"other\" (index 3) is pretty\n> > tiny, you just moved one line in the \"anderson_solver\" subroutine\n> > about 10 lines down.\n>\n> Yes, the output from\n> $ git diff :1:cicecore/cicedynB/dynamics/ice_dyn_vp.F90 :3:cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n>\n> seems to be the same as the one from\n> $ git show REBASE_HEAD\n>\n> This is a little confusing to me, in the sense that I don't understand why\n> the merge-base is what it is. At this point, I do\n>\n> $ git merge-base HEAD REBASE_HEAD\n> f4e1ae67b7d6ca36c6f3ea7c9da43d81caf24067\n>\n> Ok, so 'git merge-base' finds that the merge-base between HEAD and\n> REBASE_HEAD is HEAD; this makes sense to me (no previous commits\n> have been rewritten so far, so REBASE_HEAD is directly ahead of HEAD).\n> But, if I try to find the commit that contains\n> the blob ee4377f1ec6836fa05573976a473373906c37d9f (index 1), I find\n> REBASE_HEAD's parent:\n>\n> $ git log --all --find-object=ee4377f1ec6836fa05573976a473373906c37d9f --format='commmit %H%ntree %T%nparent %P%n%n    %s%n'\n> commmit e8bfa557d3c81b75116d6557784b0439b792a308\n> tree f6fecb8193c3b877f22bcb8f4d8d2c203e17f06f\n> parent 7a8d5a82984dfedd7fac1d7ed7c7fbd1781c1f61\n>\n>     fixup! Add Anderson acceleration for Picard iteration\n>\n> commmit 7a8d5a82984dfedd7fac1d7ed7c7fbd1781c1f61\n> tree 11fd096851015c0c16b793d9bbb5db039776483b\n> parent 63d4c73c1dd973f620307833bd363a1d5069d090\n>\n>     ice_dyn_vp: introduce 'CICE_USE_LAPACK' preprocessor macro\n>\n> $ blob=ee4377f1ec6836fa05573976a473373906c37d9f\n> $ parent=7a8d5a82984dfedd7fac1d7ed7c7fbd1781c1f61\n> $ git ls-tree -r $parent^{tree} | grep $blob\n> 100644 blob ee4377f1ec6836fa05573976a473373906c37d9f    cicecore/cicedynB/dynamics/ice_dyn_vp.F90\n>\n> I don't understand why at this point of the rebase, Git\n> determines that the merge-base between HEAD and\n> REBASE_HEAD is REBASE_HEAD's parent... this commit\n> is not even an ancestor of HEAD (or maybe I don't understand\n> what the \"merge-base\" is in this context?)...\n\nFirst, remember that this is a rebase or cherry-pick, and not a merge\n(we are not creating a new merge commit, but just a commit that\n\"cherry-picks\" the changes from one commit).  But since the wording\nand the machinery comes from a merge, let's start by discussing how\nmerge works.\n\nWhen you merge two branches (e.g. 'git merge other' will merge branch\n'other' into HEAD), git determines the merge-base, i.e. the point of\ncommon history between two commits.  For simplicity, let's assume\nthere is a common point of history and exactly one common point of\nhistory for these two commits.  Given these assumptions, we have a\nmerge-base and two commits.  Let's label the merge-base as A, the\ncommit at HEAD 'B', and the commit at 'other', 'C'.  So we are doing a\nthree-way merge between A, B, and C.\n\nThe thing about a three-way merge is besides thinking of it as a\nthree-way merge of A, B, and C, there are two other equivalent ways to\nlook at it: applying the changes between A and B to C, or applying the\nchanges between A and C to B.  These alternate ways of looking at\nthings come in handy when looking at rebases and cherry-picks.\n\nWhen cherry-picking or rebasing a commit, we do NOT want to use the\nnormal merge-base of HEAD and the commit being picked; if we did that,\nit would merge ALL the changes in the history of the commit being\npicked into the current branch instead of just the changes from the\none commit we want to cherry-pick/rebase.  Noting that we only want\nthe changes from that one commit, we can word it similarly to above by\nstating that we want to apply the changes between REBASE_HEAD^1 and\nREBASE_HEAD to HEAD.  Looking at the above wording for three-way\nmerges (\"applying the changes between A and C to B\"), that means we\nwant to do a three-way merge of REBASE_HEAD^1, HEAD, and REBASE_HEAD.\nAnd when we're done and create a new commit, we do not make a merge\ncommit but instead record HEAD as the only parent.  Hopefully, this\nmakes it clear why we use the parent of REBASE_HEAD as the\n\"merge-base\" in the merge machinery; it's not really a \"merge-base\"\nbecause we're not doing a merge, but we're using the merge machinery\nwith a special commit as the merge-base because it gives the results\nwe want.\n\nHope that helps,\nElijah\n"}]}