threads / discuss / 61448

git-cherry-pick(1) -- path

Subject: git-cherry-pick(1) -- path

## tl;dr

10 messages between May 9, 2024 and May 13, 2024.

replies: 9people: 3as markdown or json

Alejandro Colomar· May 9, 2024, 22:32 UTC · lore
Hi!

I'd be interested in being able to partially cherry-pick commits, based on a path filter (similar to how many other git(1) commands behave with -- path).

Do you have any opinions on that?

Have a lovely night! Alex

-- 
<https://www.alejandro-colomar.es/>
A client is hiring kernel driver, mm, and/or crypto developers;
contact me if interested.
Junio C Hamano· May 10, 2024, 01:15 UTC · re: Alejandro Colomar · lore

Re: git-cherry-pick(1) -- path

Alejandro Colomar <alx@kernel.org> writes:
Show 5 quoted lines
> I'd be interested in being able to partially cherry-pick commits, based
> on a path filter (similar to how many other git(1) commands behave with
> -- path).
>
> Do you have any opinions on that?
Opinions?  
Personally it is a "Meh" for me, because I would instead do
    $ git format-patch --stdout -1 $ThatCommit -- $ThisPath |
      git am -3

which would be mostly sufficient for my purpose, but I do not see any fundamental reason why it should not exist.

It is already well known that future merges from the same branch will have to deal with duplicated changes brought in by picking commits with "git cherry-pick". Having a pathspec-limited variant of "git cherry-pick" would not make the world a worse place.

Alejandro Colomar· May 10, 2024, 09:05 UTC · re: Junio C Hamano · lore

Re: git-cherry-pick(1) -- path

Hi Junio,
On Thu, May 09, 2024 at 06:15:24PM GMT, Junio C Hamano wrote:
Show 14 quoted lines
> Alejandro Colomar <alx@kernel.org> writes:
> 
> > I'd be interested in being able to partially cherry-pick commits, based
> > on a path filter (similar to how many other git(1) commands behave with
> > -- path).
> >
> > Do you have any opinions on that?
> 
> Opinions?  
> 
> Personally it is a "Meh" for me, because I would instead do
> 
>     $ git format-patch --stdout -1 $ThatCommit -- $ThisPath |
>       git am -3
Hmmm, I hadn't thought of that; very interesting!

Although I have some concerns with git-am(1); basically that it's almost clueless when there's a conflict. With git-cherry-pick(1), at least I have the ability to resolve the conflict manually.

If I find some time, I'll check if I can program that (although it would be the first time I do some contribution like that to git(1), so I may need some help). :-)

Have a lovely day! Alex

Show 7 quoted lines
> which would be mostly sufficient for my purpose, but I do not see
> any fundamental reason why it should not exist.
> 
> It is already well known that future merges from the same branch
> will have to deal with duplicated changes brought in by picking
> commits with "git cherry-pick".  Having a pathspec-limited variant
> of "git cherry-pick" would not make the world a worse place.
-- 
<https://www.alejandro-colomar.es/>
Phillip Wood· May 10, 2024, 10:00 UTC · re: Alejandro Colomar · lore

Re: git-cherry-pick(1) -- path

Hi Alex and Junio
On 10/05/2024 10:05, Alejandro Colomar wrote:
Show 10 quoted lines
> Hi Junio,
> 
> On Thu, May 09, 2024 at 06:15:24PM GMT, Junio C Hamano wrote:
>> Alejandro Colomar <alx@kernel.org> writes:
>>
>>> I'd be interested in being able to partially cherry-pick commits, based
>>> on a path filter (similar to how many other git(1) commands behave with
>>> -- path).
>>>
>>> Do you have any opinions on that?

I'd be happy to see a patch that adds that (I sometimes find myself wishing "git cherry-pick" had a "--patch" option to do something similar but that's a bit of a tangent here)

Show 7 quoted lines
>>      $ git format-patch --stdout -1 $ThatCommit -- $ThisPath |
>>        git am -3
> 
> Hmmm, I hadn't thought of that; very interesting!
> 
> Although I have some concerns with git-am(1); basically that it's almost
> clueless when there's a conflict.

"git am -3" should be fine here as you're guaranteed to have the necessary blobs available to create conflicts - this is what "git rebase --apply" does.

> If I find some time, I'll check if I can program that (although it would
> be the first time I do some contribution like that to git(1), so I may
> need some help).  :-)

As far as the implementation goes I haven't thought too deeply but I suspect we'd want to create a couple of trees based on the commit we want to cherry-pick and its parent filtered by the pathspec and use those in the tree-way merge with HEAD.

Best Wishes
Phillip
Junio C Hamano· May 10, 2024, 17:03 UTC · re: Phillip Wood · lore

Re: git-cherry-pick(1) -- path

Phillip Wood <phillip.wood123@gmail.com> writes:
Show 10 quoted lines
>>>      $ git format-patch --stdout -1 $ThatCommit -- $ThisPath |
>>>        git am -3
>> Hmmm, I hadn't thought of that; very interesting!
>> Although I have some concerns with git-am(1); basically that it's
>> almost
>> clueless when there's a conflict.
>
> "git am -3" should be fine here as you're guaranteed to have the
> necessary blobs available to create conflicts - this is what "git
> rebase --apply" does.

Good thing to point out. "am -3" is just as good for this purpose and "almost clueless" is a derogatory comment that requires an apology ;-)

> As far as the implementation goes I haven't thought too deeply but I
> suspect we'd want to create a couple of trees based on the commit we
> want to cherry-pick and its parent filtered by the pathspec and use
> those in the tree-way merge with HEAD.

If we were to use the ort machinery, it may not be too bad to use the pathspec only at the final writeout phase. That is, perform a full cherry-pick in the in-core index, reset all the entries in the in-core index back to HEAD that are outside the given pathspec, and then write out the result to the working tree. That way, an old change that was made to paths at the original location can be cherry picked to a much newer tree after these paths have been moved to a different location. Doing the same with the recursive machinery would be missier but perhaps the more recent merge-tree that uses the ort machinery to work purely in-core might be a good way to go.

Alejandro Colomar· May 11, 2024, 11:46 UTC · re: Junio C Hamano · lore

Re: git-cherry-pick(1) -- path

Hi Phillip, Junio,
On Fri, May 10, 2024 at 10:03:31AM GMT, Junio C Hamano wrote:
Show 16 quoted lines
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
> >>>      $ git format-patch --stdout -1 $ThatCommit -- $ThisPath |
> >>>        git am -3
> >> Hmmm, I hadn't thought of that; very interesting!
> >> Although I have some concerns with git-am(1); basically that it's
> >> almost
> >> clueless when there's a conflict.
> >
> > "git am -3" should be fine here as you're guaranteed to have the
> > necessary blobs available to create conflicts - this is what "git
> > rebase --apply" does.
> 
> Good thing to point out.  "am -3" is just as good for this purpose
> and "almost clueless" is a derogatory comment that requires an
> apology ;-)

Huh, I am quite surprised by `git am -3`. I've tried it just now, and it's amazing. I certainly must apologize. :-)

I tried it yesterday, but the patches were from a different repo, and not available locally, so it really didn't do anything. But now I tried it within the same repo, and it's really nice!

Show 15 quoted lines
> > As far as the implementation goes I haven't thought too deeply but I
> > suspect we'd want to create a couple of trees based on the commit we
> > want to cherry-pick and its parent filtered by the pathspec and use
> > those in the tree-way merge with HEAD.
> 
> If we were to use the ort machinery, it may not be too bad to use
> the pathspec only at the final writeout phase.  That is, perform a
> full cherry-pick in the in-core index, reset all the entries in the
> in-core index back to HEAD that are outside the given pathspec, and
> then write out the result to the working tree.  That way, an old
> change that was made to paths at the original location can be cherry
> picked to a much newer tree after these paths have been moved to a
> different location.  Doing the same with the recursive machinery
> would be missier but perhaps the more recent merge-tree that uses
> the ort machinery to work purely in-core might be a good way to go.

I didn't understand the last part well, but I guess I may do when I start researching into it. :)

Apart from <builtin/revert.c>, do you recommend I look into any particular files?

Thanks!

And have a lovely weekend! Alex

-- 
<https://www.alejandro-colomar.es/>
A client is hiring kernel driver, mm, and/or crypto developers;
contact me if interested.
Phillip Wood· May 11, 2024, 15:01 UTC · re: Alejandro Colomar · lore

Re: git-cherry-pick(1) -- path

Hi Alex and Junio
On 11/05/2024 12:46, Alejandro Colomar wrote:
Show 34 quoted lines
> Hi Phillip, Junio,
> 
> On Fri, May 10, 2024 at 10:03:31AM GMT, Junio C Hamano wrote:
>> Phillip Wood <phillip.wood123@gmail.com> writes:
>>
>>>>>       $ git format-patch --stdout -1 $ThatCommit -- $ThisPath |
>>>>>         git am -3
>>>> Hmmm, I hadn't thought of that; very interesting!
>>>> Although I have some concerns with git-am(1); basically that it's
>>>> almost
>>>> clueless when there's a conflict.
>>>
>>> "git am -3" should be fine here as you're guaranteed to have the
>>> necessary blobs available to create conflicts - this is what "git
>>> rebase --apply" does.
>>
>> Good thing to point out.  "am -3" is just as good for this purpose
>> and "almost clueless" is a derogatory comment that requires an
>> apology ;-)
> 
> Huh, I am quite surprised by `git am -3`.  I've tried it just now, and
> it's amazing.  I certainly must apologize.  :-)
> 
> I tried it yesterday, but the patches were from a different repo, and
> not available locally, so it really didn't do anything.  But now I tried
> it within the same repo, and it's really nice!
> 
>>> As far as the implementation goes I haven't thought too deeply but I
>>> suspect we'd want to create a couple of trees based on the commit we
>>> want to cherry-pick and its parent filtered by the pathspec and use
>>> those in the tree-way merge with HEAD.
>>
>> If we were to use the ort machinery, it may not be too bad to use
>> the pathspec only at the final writeout phase.

That would be tempting if cherry-pick didn't have a "--strategy" option. I think we need something more generic to cope with that.

Show 9 quoted lines
>>  That is, perform a
>> full cherry-pick in the in-core index, reset all the entries in the
>> in-core index back to HEAD that are outside the given pathspec, and
>> then write out the result to the working tree.  That way, an old
>> change that was made to paths at the original location can be cherry
>> picked to a much newer tree after these paths have been moved to a
>> different location.  Doing the same with the recursive machinery
>> would be missier but perhaps the more recent merge-tree that uses
>> the ort machinery to work purely in-core might be a good way to go.

My hope was that the changes required to create a couple of new trees that are then used instead of the original commits when a pathspec is given would be fairly localized.

Show 5 quoted lines
> I didn't understand the last part well, but I guess I may do when I
> start researching into it.  :)
> 
> Apart from <builtin/revert.c>, do you recommend I look into any
> particular files?

sequencer.c. If we go for the "write new trees and use those in the merge" approach then we'd need to change do_pick_commit() to create the trees and we'd probably want to change do_recursive_merge() to take trees rather than commits. We'd also need to add a new pathspec member to struct replay_opts to pass the pathspec around.

Best Wishes
Phillip
Alejandro Colomar· May 11, 2024, 20:08 UTC · re: Phillip Wood · lore

Re: git-cherry-pick(1) -- path

Hi Phillip,
On Sat, May 11, 2024 at 04:01:18PM GMT, Phillip Wood wrote:
Show 5 quoted lines
> sequencer.c. If we go for the "write new trees and use those in the merge"
> approach then we'd need to change do_pick_commit() to create the trees and
> we'd probably want to change do_recursive_merge() to take trees rather than
> commits. We'd also need to add a new pathspec member to struct replay_opts
> to pass the pathspec around.

I've been thinking this evening that since `git format-patch ... | git am -3` works so well, and since the behavior of cherry-pick -- path isn't so obvious (we're discussing different strategies), maybe we should just not do it. I fell in love with am -3.

:-3

Have a lovely night! Alex

-- 
<https://www.alejandro-colomar.es/>
A client is hiring kernel driver, mm, and/or crypto developers;
contact me if interested.
Alejandro Colomar· May 12, 2024, 15:35 UTC · re: Alejandro Colomar · lore

Re: git-cherry-pick(1) -- path

Hi,
On Sat, May 11, 2024 at 10:08:47PM GMT, Alejandro Colomar wrote:
Show 13 quoted lines
> Hi Phillip,
> 
> On Sat, May 11, 2024 at 04:01:18PM GMT, Phillip Wood wrote:
> > sequencer.c. If we go for the "write new trees and use those in the merge"
> > approach then we'd need to change do_pick_commit() to create the trees and
> > we'd probably want to change do_recursive_merge() to take trees rather than
> > commits. We'd also need to add a new pathspec member to struct replay_opts
> > to pass the pathspec around.
> 
> I've been thinking this evening that since
> `git format-patch ... | git am -3` works so well, and since the behavior
> of cherry-pick -- path isn't so obvious (we're discussing different
> strategies), maybe we should just not do it.  I fell in love with am -3.
In the end, I'm using the following:
$ git log --oneline 2024a..tz/main -- tzfile.5 tzselect.8 zic.8 zdump.8 \
| awk '{print $1}' \
| tac \
| while read c; do
	git format-patch --stdout -1 $c -- tzfile.5 tzselect.8 z*.8 \
	| sed '/^---$/s/^/\n/' \
	| sed "/^---$/i Cherry-picked-from: tz.git $( \
			git log -1 --oneline --abbrev=12 $c \
			| awk '{print $1}' \
		) (\"$( \
			git log -1 --oneline $c \
			| sed 's/[^ ]* //' \
		)\")";
done \
| git am -3 -s;

And it works like a charm. If I had to spell that as a git-cherry-pick(1) command, I'd say `git cherry-pick -x -s 2024a..tz/main -- tzfile.5 tzselect.8 zic.8 zdump.8`

BTW, there's something I noticed when I had an accident (forgot to tac(1) the commit list): the git-am(1) conflicts session isn't as good as a cherry-pick one: it doesn't show which commits are being applied. If you're in the middle of a 50-commit cherry-pick, it's hard to see where it's going wrong. So maybe adding this functionallity to git-cherry-pick(1) could be a good thing.

Have a lovely day! Alex

-- 
<https://www.alejandro-colomar.es/>
Phillip Wood· May 13, 2024, 15:16 UTC · re: Alejandro Colomar · lore

Re: git-cherry-pick(1) -- path

Hi Alex
On 11/05/2024 21:08, Alejandro Colomar wrote:
> I've been thinking this evening that since
> `git format-patch ... | git am -3` works so well, and since the behavior
> of cherry-pick -- path isn't so obvious (we're discussing different
> strategies), maybe we should just not do it.  I fell in love with am -3.
I agree that using "format-patch" and "am" is a good enough solution
Thanks
Phillip

← back to recent threads