threads / discuss / 57948

Cherry-Pick without affecting working tree / index?

Subject: Cherry-Pick without affecting working tree / index?

## tl;dr

3 messages between Jun 2, 2022 and Jun 3, 2022.

replies: 2people: 2as markdown or json

Tao Klerks· Jun 2, 2022, 17:08 UTC · lore
Hi folks,

I'm wondering whether it's possible to perform a (non-conflicting) cherry pick without impacting the working tree (or index).

I understand Elijah Newren has been working on git-merge-tree changes that would allow for simulating (and even saving) merge commits without affecting the index or working tree, and I could imagine that's a piece of how such a thing could/should work, but I'm not terribly clear on the relationship between merges and cherry-picks.

It *seems* as though I could enact something functionally equivalent to a cherry-pick by first creating a (temporary) "--ours" merge commit on the target branch, pretending to have merged the parent commit of the cherry-pickable one, and then merging the cherry-pick commit itself on top of that. The resulting tree could be used as the basis for a final commit on top of the original tip of the target branch, if that merge were clean, and otherwise fail saying "there are conflicts, go do things properly in a working tree pls".

I'm not sure whether this is the right way to conceive of cherry-picking, however, or whether it makes more sense to conceive of it as a single-commit rebase. Is there a relationship between git-merge-tree and rebases? Is there an aspiration to develop "server side rebase" also at some stage?

Thanks for any help understanding how cherry-picks conceptually "work".

Thanks, Tao

Elijah Newren· Jun 2, 2022, 23:52 UTC · re: Tao Klerks · lore

Re: Cherry-Pick without affecting working tree / index?

On Thu, Jun 2, 2022 at 10:08 AM Tao Klerks <tao@klerks.biz> wrote:
Show 24 quoted lines
>
> Hi folks,
>
> I'm wondering whether it's possible to perform a (non-conflicting)
> cherry pick without impacting the working tree (or index).
>
> I understand Elijah Newren has been working on git-merge-tree changes
> that would allow for simulating (and even saving) merge commits
> without affecting the index or working tree, and I could imagine
> that's a piece of how such a thing could/should work, but I'm not
> terribly clear on the relationship between merges and cherry-picks.
>
> It *seems* as though I could enact something functionally equivalent
> to a cherry-pick by first creating a (temporary) "--ours" merge commit
> on the target branch, pretending to have merged the parent commit of
> the cherry-pickable one, and then merging the cherry-pick commit
> itself on top of that. The resulting tree could be used as the basis
> for a final commit on top of the original tip of the target branch, if
> that merge were clean, and otherwise fail saying "there are conflicts,
> go do things properly in a working tree pls".
>
> I'm not sure whether this is the right way to conceive of
> cherry-picking, however, or whether it makes more sense to conceive of
> it as a single-commit rebase.

The merge --ours stuff is going down a weird path that I don't recommend, but thinking of it as a single-commit rebase is good. In fact, the default rebase backend was originally written by calling cherry-pick for each commit in question.

> Is there a relationship between
> git-merge-tree and rebases?

The patches I submitted do not have the ability for rebases to be built from git-merge-tree. There's a debate over whether my series should be tweaked to enable it. Peruse the thread over at https://lore.kernel.org/git/xmqqh78nj0q0.fsf@gitster.g/ if you want to read some of the discussion, as well as see discussion of how merging and cherry-picks/rebases are related.

> Is there an aspiration to develop "server
> side rebase" also at some stage?

Yes, already in progress and possibly usable for simple cases. Haven't had some time to work on it for a while (~4 months, sigh), but will definitely get some time in late June/early July to carry it on. You can check out the "replay" branch of github.com/newren/git if you're curious.

Tao Klerks· Jun 3, 2022, 07:46 UTC · re: Elijah Newren · lore

Re: Cherry-Pick without affecting working tree / index?

On Fri, Jun 3, 2022 at 1:52 AM Elijah Newren <newren@gmail.com> wrote:
>
> On Thu, Jun 2, 2022 at 10:08 AM Tao Klerks <tao@klerks.biz> wrote:
> >
<snip>
Show 19 quoted lines
> >
> > It *seems* as though I could enact something functionally equivalent
> > to a cherry-pick by first creating a (temporary) "--ours" merge commit
> > on the target branch, pretending to have merged the parent commit of
> > the cherry-pickable one, and then merging the cherry-pick commit
> > itself on top of that. The resulting tree could be used as the basis
> > for a final commit on top of the original tip of the target branch, if
> > that merge were clean, and otherwise fail saying "there are conflicts,
> > go do things properly in a working tree pls".
> >
> > I'm not sure whether this is the right way to conceive of
> > cherry-picking, however, or whether it makes more sense to conceive of
> > it as a single-commit rebase.
>
> The merge --ours stuff is going down a weird path that I don't
> recommend, but thinking of it as a single-commit rebase is good.  In
> fact, the default rebase backend was originally written by calling
> cherry-pick for each commit in question.
>
Thanks so much for your fast feedback!

When you say "The merge --ours stuff is going down a weird path that I don't recommend", I would love to understand better what you mean.

My testing so far is basic at best, and I had a typo (I meant "git merge -s ours" rather than "git merge --ours"), but in principle what I described does seem to *work* in most cases?

For example, imagine I want to cherry-pick Johannes Schindelin's commit b44855743b1674caf3bd4f42814473771b129c48 onto current master in Junio's repo - I can do it the simple way:

git checkout origin/master git cherry-pick b44855743b1674caf3bd4f42814473771b129c48

Or I can do it the "the only tool I have available is merge, so I need to play with the merge base" way:

git checkout origin/master TARGET_COMMIT=b44855743b1674caf3bd4f42814473771b129c48 git merge $TARGET_COMMIT~1 -s ours -m whatever git merge $TARGET_COMMIT -m whateverelse git log --format=%B -1 $TARGET_COMMIT | \ GIT_AUTHOR_NAME="$(git log --format=%an -1 $TARGET_COMMIT)" \ GIT_AUTHOR_EMAIL="$(git log --format=%ae -1 $TARGET_COMMIT)" \ GIT_AUTHOR_DATE="$(git log --format=%at -1 $TARGET_COMMIT)" \ git commit-tree -p origin/master `git rev-parse HEAD^{tree}` #and do something with the resulting commit, eg branch -f

One limitation here is that it doesn't work to "cherry-pick" commits that are already in the history of the target branch (which could be solved with a temporary shallow graft? :D ). Maybe more important is that it's a crazy-convoluted way of doing things...

Is there something "theoretically" wrong with this way of thinking about it, or is your concern more that this is like using a stick of dynamite to kill a fly? (likely effective, but not recommended?)

Please note, having read the thread below, I understand you have some hard-won experience around the use of scripting approaches for the implementation of actual git commands - I never stated this explicitly above, but I'm asking partially as an intellectual exercise, partially wrt something I might implement in custom tooling for specific workflows in a specific context. At no point am I suggesting the above would be the right way for an official (new?) git command to do its work.

Show 10 quoted lines
> > Is there a relationship between
> > git-merge-tree and rebases?
>
> The patches I submitted do not have the ability for rebases to be
> built from git-merge-tree.  There's a debate over whether my series
> should be tweaked to enable it.  Peruse the thread over at
> https://lore.kernel.org/git/xmqqh78nj0q0.fsf@gitster.g/ if you want to
> read some of the discussion, as well as see discussion of how merging
> and cherry-picks/rebases are related.
>

Thanks very much! I guess it's a little late to chime in on that thread, but for what it's worth, I agree with Junio that it would be ideal if "merge-tree" were able to do that "gimme (arbitrary) trees and I'll merge'em" operation - not that I would expect any official git commands to invoke this recursively (I understand the concerns over poor design / unnecessary complexity driven by a scripting approach), but that would be a powerful tool for people who want to script their own crazy use cases - eg a less-bad version of what I outlined above, without the need for the "git merge -s ours" commit establishing the desired merge base.

That said, I get lost in the discussion of what the right set of commands / distribution of responsibility should be; given the *name*, I would expect "gimme three trees and I'll give you a fourth with conflict data" to be an operation that fits in that existing command, and I would expect "do a server-side merge or a server-side rebase through to a new (set of) merge or rebased commit(s)" to be separate (new?) commands.

Show 8 quoted lines
> > Is there an aspiration to develop "server
> > side rebase" also at some stage?
>
> Yes, already in progress and possibly usable for simple cases.
> Haven't had some time to work on it for a while (~4 months, sigh), but
> will definitely get some time in late June/early July to carry it on.
> You can check out the "replay" branch of github.com/newren/git if
> you're curious.
Thank you, will look!

← back to recent threads