{"thread":{"id":"57948","subject":"Cherry-Pick without affecting working tree / index?","startedAt":"2022-06-02T17:08:46Z","lastAt":"2022-06-03T07:46:40Z","messageCount":3,"participants":["Tao Klerks","Elijah Newren"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"456531","messageId":"CAPMMpoj8CyhB=g0=HD2Y2w6+mkGVRsgoq6zsb5XCTt95uDELog@mail.gmail.com","threadId":"57948","inReplyTo":null,"subject":"Cherry-Pick without affecting working tree / index?","fromName":"Tao Klerks","fromEmail":"tao@klerks.biz","sentAt":"2022-06-02T17:08:30Z","receivedAt":"2022-06-02T17:08:46Z","isPatch":false,"sender":{"key":"tao@klerks.biz","avatar":"https://avatars.githubusercontent.com/u/531704?v=4"},"body":"Hi folks,\n\nI'm wondering whether it's possible to perform a (non-conflicting)\ncherry pick without impacting the working tree (or index).\n\nI understand Elijah Newren has been working on git-merge-tree changes\nthat would allow for simulating (and even saving) merge commits\nwithout affecting the index or working tree, and I could imagine\nthat's a piece of how such a thing could/should work, but I'm not\nterribly clear on the relationship between merges and cherry-picks.\n\nIt *seems* as though I could enact something functionally equivalent\nto a cherry-pick by first creating a (temporary) \"--ours\" merge commit\non the target branch, pretending to have merged the parent commit of\nthe cherry-pickable one, and then merging the cherry-pick commit\nitself on top of that. The resulting tree could be used as the basis\nfor a final commit on top of the original tip of the target branch, if\nthat merge were clean, and otherwise fail saying \"there are conflicts,\ngo do things properly in a working tree pls\".\n\nI'm not sure whether this is the right way to conceive of\ncherry-picking, however, or whether it makes more sense to conceive of\nit as a single-commit rebase. Is there a relationship between\ngit-merge-tree and rebases? Is there an aspiration to develop \"server\nside rebase\" also at some stage?\n\nThanks for any help understanding how cherry-picks conceptually \"work\".\n\nThanks,\nTao\n"},{"id":"456548","messageId":"CABPp-BF4kD8uieZ1QWLbzejhuhaZA7rYfDR+8dGrteL_4UhkHQ@mail.gmail.com","threadId":"57948","inReplyTo":"CAPMMpoj8CyhB=g0=HD2Y2w6+mkGVRsgoq6zsb5XCTt95uDELog@mail.gmail.com","subject":"Re: Cherry-Pick without affecting working tree / index?","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2022-06-02T23:52:34Z","receivedAt":"2022-06-02T23:52:52Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, Jun 2, 2022 at 10:08 AM Tao Klerks <tao@klerks.biz> wrote:\n>\n> Hi folks,\n>\n> I'm wondering whether it's possible to perform a (non-conflicting)\n> cherry pick without impacting the working tree (or index).\n>\n> I understand Elijah Newren has been working on git-merge-tree changes\n> that would allow for simulating (and even saving) merge commits\n> without affecting the index or working tree, and I could imagine\n> that's a piece of how such a thing could/should work, but I'm not\n> terribly clear on the relationship between merges and cherry-picks.\n>\n> It *seems* as though I could enact something functionally equivalent\n> to a cherry-pick by first creating a (temporary) \"--ours\" merge commit\n> on the target branch, pretending to have merged the parent commit of\n> the cherry-pickable one, and then merging the cherry-pick commit\n> itself on top of that. The resulting tree could be used as the basis\n> for a final commit on top of the original tip of the target branch, if\n> that merge were clean, and otherwise fail saying \"there are conflicts,\n> go do things properly in a working tree pls\".\n>\n> I'm not sure whether this is the right way to conceive of\n> cherry-picking, however, or whether it makes more sense to conceive of\n> it as a single-commit rebase.\n\nThe merge --ours stuff is going down a weird path that I don't\nrecommend, but thinking of it as a single-commit rebase is good.  In\nfact, the default rebase backend was originally written by calling\ncherry-pick for each commit in question.\n\n> Is there a relationship between\n> git-merge-tree and rebases?\n\nThe patches I submitted do not have the ability for rebases to be\nbuilt from git-merge-tree.  There's a debate over whether my series\nshould be tweaked to enable it.  Peruse the thread over at\nhttps://lore.kernel.org/git/xmqqh78nj0q0.fsf@gitster.g/ if you want to\nread some of the discussion, as well as see discussion of how merging\nand cherry-picks/rebases are related.\n\n> Is there an aspiration to develop \"server\n> side rebase\" also at some stage?\n\nYes, already in progress and possibly usable for simple cases.\nHaven't had some time to work on it for a while (~4 months, sigh), but\nwill definitely get some time in late June/early July to carry it on.\nYou can check out the \"replay\" branch of github.com/newren/git if\nyou're curious.\n"},{"id":"456551","messageId":"CAPMMpoiKR1LRYO4zpJb09n3-pUzcZfpWCm_trRq=ZhTawN7aEw@mail.gmail.com","threadId":"57948","inReplyTo":"CABPp-BF4kD8uieZ1QWLbzejhuhaZA7rYfDR+8dGrteL_4UhkHQ@mail.gmail.com","subject":"Re: Cherry-Pick without affecting working tree / index?","fromName":"Tao Klerks","fromEmail":"tao@klerks.biz","sentAt":"2022-06-03T07:46:23Z","receivedAt":"2022-06-03T07:46:40Z","isPatch":false,"sender":{"key":"tao@klerks.biz","avatar":"https://avatars.githubusercontent.com/u/531704?v=4"},"body":"On Fri, Jun 3, 2022 at 1:52 AM Elijah Newren <newren@gmail.com> wrote:\n>\n> On Thu, Jun 2, 2022 at 10:08 AM Tao Klerks <tao@klerks.biz> wrote:\n> >\n<snip>\n> >\n> > It *seems* as though I could enact something functionally equivalent\n> > to a cherry-pick by first creating a (temporary) \"--ours\" merge commit\n> > on the target branch, pretending to have merged the parent commit of\n> > the cherry-pickable one, and then merging the cherry-pick commit\n> > itself on top of that. The resulting tree could be used as the basis\n> > for a final commit on top of the original tip of the target branch, if\n> > that merge were clean, and otherwise fail saying \"there are conflicts,\n> > go do things properly in a working tree pls\".\n> >\n> > I'm not sure whether this is the right way to conceive of\n> > cherry-picking, however, or whether it makes more sense to conceive of\n> > it as a single-commit rebase.\n>\n> The merge --ours stuff is going down a weird path that I don't\n> recommend, but thinking of it as a single-commit rebase is good.  In\n> fact, the default rebase backend was originally written by calling\n> cherry-pick for each commit in question.\n>\n\nThanks so much for your fast feedback!\n\nWhen you say \"The merge --ours stuff is going down a weird path that I\ndon't recommend\", I would love to understand better what you mean.\n\nMy testing so far is basic at best, and I had a typo (I meant \"git\nmerge -s ours\" rather than \"git merge --ours\"), but in principle what\nI described does seem to *work* in most cases?\n\nFor example, imagine I want to cherry-pick Johannes Schindelin's\ncommit b44855743b1674caf3bd4f42814473771b129c48 onto current master in\nJunio's repo - I can do it the simple way:\n\ngit checkout origin/master\ngit cherry-pick b44855743b1674caf3bd4f42814473771b129c48\n\nOr I can do it the \"the only tool I have available is merge, so I need\nto play with the merge base\" way:\n\ngit checkout origin/master\nTARGET_COMMIT=b44855743b1674caf3bd4f42814473771b129c48\ngit merge $TARGET_COMMIT~1 -s ours -m whatever\ngit merge $TARGET_COMMIT -m whateverelse\ngit log --format=%B -1 $TARGET_COMMIT | \\\nGIT_AUTHOR_NAME=\"$(git log --format=%an -1 $TARGET_COMMIT)\" \\\nGIT_AUTHOR_EMAIL=\"$(git log --format=%ae -1 $TARGET_COMMIT)\" \\\nGIT_AUTHOR_DATE=\"$(git log --format=%at -1 $TARGET_COMMIT)\" \\\ngit commit-tree -p origin/master `git rev-parse HEAD^{tree}`\n#and do something with the resulting commit, eg branch -f\n\nOne limitation here is that it doesn't work to \"cherry-pick\" commits\nthat are already in the history of the target branch (which could be\nsolved with a temporary shallow graft? :D ). Maybe more important is\nthat it's a crazy-convoluted way of doing things...\n\nIs there something \"theoretically\" wrong with this way of thinking\nabout it, or is your concern more that this is like using a stick of\ndynamite to kill a fly? (likely effective, but not recommended?)\n\nPlease note, having read the thread below, I understand you have some\nhard-won experience around the use of scripting approaches for the\nimplementation of actual git commands - I never stated this explicitly\nabove, but I'm asking partially as an intellectual exercise, partially\nwrt something I might implement in custom tooling for specific\nworkflows in a specific context. At no point am I suggesting the above\nwould be the right way for an official (new?) git command to do its\nwork.\n\n> > Is there a relationship between\n> > git-merge-tree and rebases?\n>\n> The patches I submitted do not have the ability for rebases to be\n> built from git-merge-tree.  There's a debate over whether my series\n> should be tweaked to enable it.  Peruse the thread over at\n> https://lore.kernel.org/git/xmqqh78nj0q0.fsf@gitster.g/ if you want to\n> read some of the discussion, as well as see discussion of how merging\n> and cherry-picks/rebases are related.\n>\n\nThanks very much! I guess it's a little late to chime in on that\nthread, but for what it's worth, I agree with Junio that it would be\nideal if \"merge-tree\" were able to do that \"gimme (arbitrary) trees\nand I'll merge'em\" operation - not that I would expect any official\ngit commands to invoke this recursively (I understand the concerns\nover poor design / unnecessary complexity driven by a scripting\napproach), but that would be a powerful tool for people who want to\nscript their own crazy use cases - eg a less-bad version of what I\noutlined above, without the need for the \"git merge -s ours\" commit\nestablishing the desired merge base.\n\nThat said, I get lost in the discussion of what the right set of\ncommands / distribution of responsibility should be; given the *name*,\nI would expect \"gimme three trees and I'll give you a fourth with\nconflict data\" to be an operation that fits in that existing command,\nand I would expect \"do a server-side merge or a server-side rebase\nthrough to a new (set of) merge or rebased commit(s)\" to be separate\n(new?) commands.\n\n> > Is there an aspiration to develop \"server\n> > side rebase\" also at some stage?\n>\n> Yes, already in progress and possibly usable for simple cases.\n> Haven't had some time to work on it for a while (~4 months, sigh), but\n> will definitely get some time in late June/early July to carry it on.\n> You can check out the \"replay\" branch of github.com/newren/git if\n> you're curious.\n\nThank you, will look!\n"}]}