* [PATCH 0/2] add -p: a couple of hunk splitting fixes @ 2025-02-21 14:57 Phillip Wood via GitGitGadget 2025-02-21 14:57 ` [PATCH 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget ` (2 more replies) 0 siblings, 3 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-02-21 14:57 UTC (permalink / raw) To: git; +Cc: Phillip Wood This series fixes a couple of infelicities when splitting hunks that have already been selected or edited which I noticed a while ago when preparing the test for 'pw/add-patch-with-suppress-blank-empty'. Phillip Wood (2): add -p: mark split hunks as undecided add-patch: update hunk splitability after editing add-patch.c | 15 +++++++++++++-- t/t3701-add-interactive.sh | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) base-commit: 03944513488db4a81fdb4c21c3b515e4cb260b05 Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1863%2Fphillipwood%2Fadd-p-split-hunks-are-undecided-v1 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1863/phillipwood/add-p-split-hunks-are-undecided-v1 Pull-Request: https://github.com/gitgitgadget/git/pull/1863 -- gitgitgadget ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-21 14:57 [PATCH 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget @ 2025-02-21 14:57 ` Phillip Wood via GitGitGadget 2025-02-21 19:52 ` Justin Tobler 2025-02-21 21:31 ` Junio C Hamano 2025-02-21 14:57 ` [PATCH 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 2025-09-15 15:29 ` [PATCH v2 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2 siblings, 2 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-02-21 14:57 UTC (permalink / raw) To: git; +Cc: Phillip Wood, Phillip Wood From: Phillip Wood <phillip.wood@dunelm.org.uk> When a hunk is split each of the new hunks inherits whether it is selected or not from the original hunk. This means that if a selected hunk is split all of the new hunks are selected and the user is not asked whether or not they want to select the new hunks. This is unfortunate as the user is presumably splitting the original hunk because they only want to select some sub-set of it. Fix this by marking all the new hunks as "undecided" so that we prompt the user to decide whether to select them or not. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> --- add-patch.c | 3 ++- t/t3701-add-interactive.sh | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/add-patch.c b/add-patch.c index 95c67d8c80c..f44f98275cc 100644 --- a/add-patch.c +++ b/add-patch.c @@ -953,6 +953,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, * sizeof(*hunk)); hunk = file_diff->hunk + hunk_index; hunk->splittable_into = 1; + hunk->use = UNDECIDED_HUNK; memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); header = &hunk->header; @@ -1054,7 +1055,7 @@ next_hunk_line: hunk++; hunk->splittable_into = 1; - hunk->use = hunk[-1].use; + hunk->use = UNDECIDED_HUNK; header = &hunk->header; header->old_count = header->new_count = context_line_count; diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index b8a05d95f3f..760f3d0d30f 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -1230,4 +1230,14 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' test_cmp expect actual ' +test_expect_success 'splitting previous hunk marks split hunks as undecided' ' + test_write_lines a " " b c d e f g h i j k >file && + git add file && + test_write_lines x " " b y d e f g h i j x >file && + test_write_lines n K s n y q | git add -p file && + git cat-file blob :file >actual && + test_write_lines a " " b y d e f g h i j k >expect && + test_cmp expect actual +' + test_done -- gitgitgadget ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-21 14:57 ` [PATCH 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget @ 2025-02-21 19:52 ` Justin Tobler 2025-02-21 21:31 ` Junio C Hamano 1 sibling, 0 replies; 27+ messages in thread From: Justin Tobler @ 2025-02-21 19:52 UTC (permalink / raw) To: Phillip Wood via GitGitGadget; +Cc: git, Phillip Wood On 25/02/21 02:57PM, Phillip Wood via GitGitGadget wrote: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > When a hunk is split each of the new hunks inherits whether it is > selected or not from the original hunk. This means that if a selected > hunk is split all of the new hunks are selected and the user is not asked > whether or not they want to select the new hunks. This is unfortunate as > the user is presumably splitting the original hunk because they only > want to select some sub-set of it. Fix this by marking all the new hunks > as "undecided" so that we prompt the user to decide whether to select > them or not. Ok, each hunk may have {UNDECIDED,SKIP,USE}_HUNK set to denote its current "use" state. When splitting a hunk, the new hunks always use the previous hunk's value. This means that, if the hunk being split is already set to skip or use, the new hunks from the split will inherit the same value. If a user wants to split a hunk, they likely intend to select only a portion of the hunk. Setting each of the new hunks to same value may not be the most intuitive behavior in this case. Resetting the hunk "use" value results the user being prompted for each of these hunks again. If you have a very large hunk that would get split into many smaller hunks, this does mean that you will have to explicitly set the value for each now. If the user only wanted to change a small portion, this could be a bit tedious. I'm not sure this is a big setback though. > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> > --- > add-patch.c | 3 ++- > t/t3701-add-interactive.sh | 10 ++++++++++ > 2 files changed, 12 insertions(+), 1 deletion(-) > > diff --git a/add-patch.c b/add-patch.c > index 95c67d8c80c..f44f98275cc 100644 > --- a/add-patch.c > +++ b/add-patch.c > @@ -953,6 +953,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, > * sizeof(*hunk)); > hunk = file_diff->hunk + hunk_index; > hunk->splittable_into = 1; > + hunk->use = UNDECIDED_HUNK; Ok, we reset the current hunk to be undecided. Makes sense > memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); > > header = &hunk->header; > @@ -1054,7 +1055,7 @@ next_hunk_line: > > hunk++; > hunk->splittable_into = 1; > - hunk->use = hunk[-1].use; > + hunk->use = UNDECIDED_HUNK; Here each of the new hunks are explicitly set to be undecided. Since we always override the initial hunk to be undecided, I think the new hunks would already be set undecided as well. I don't think it hurts to be explicit though. -Justin > header = &hunk->header; > > header->old_count = header->new_count = context_line_count; > diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh > index b8a05d95f3f..760f3d0d30f 100755 > --- a/t/t3701-add-interactive.sh > +++ b/t/t3701-add-interactive.sh > @@ -1230,4 +1230,14 @@ test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' > test_cmp expect actual > ' > > +test_expect_success 'splitting previous hunk marks split hunks as undecided' ' > + test_write_lines a " " b c d e f g h i j k >file && > + git add file && > + test_write_lines x " " b y d e f g h i j x >file && > + test_write_lines n K s n y q | git add -p file && > + git cat-file blob :file >actual && > + test_write_lines a " " b y d e f g h i j k >expect && > + test_cmp expect actual > +' > + > test_done > -- > gitgitgadget > > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-21 14:57 ` [PATCH 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-02-21 19:52 ` Justin Tobler @ 2025-02-21 21:31 ` Junio C Hamano 2025-02-26 14:40 ` phillip.wood123 1 sibling, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-02-21 21:31 UTC (permalink / raw) To: Phillip Wood via GitGitGadget; +Cc: git, Phillip Wood "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > When a hunk is split each of the new hunks inherits whether it is > selected or not from the original hunk. This means that if a selected > hunk is split all of the new hunks are selected and the user is not asked > whether or not they want to select the new hunks. This is unfortunate as > the user is presumably splitting the original hunk because they only > want to select some sub-set of it. Fix this by marking all the new hunks > as "undecided" so that we prompt the user to decide whether to select > them or not. Good. I am very sure that the design of the current behaviour goes back to the very original version of "add -p" with hunk splitting I invented; I simply never considered a workflow where people may first select and say "oops, let me take it back and redo it". What I am getting at is that I do not think the current behaviour is something I designed it to be with too much thought, and debeting if it makes sense or it would be better to force them to be undecided is probably a good thing to do now. Having said that, I have one small concern about forcing them to be undecided. This now allows it to 1. Add the whole hunk 2. Go back (with K) to that already chosen hunk 3. Split and makes the resulting minihunks more obvious, as you do not have to use the uppercase J/K to visit them. But if one is very used to do this intentionally (as opposed to "oops, let me take it back"), this would be a usability regression. "Ah, here is a big hunk with 10 changes, most of which I like, but one of the lines I do not want to include" in which case I may do the "Add the hunk to grab 10 changes, visit that decided-to-be-used hunk, split, and then visit the one minihunk that I want to eject and say 'n'". This makes the workflow simpler and more stupid by requiring the 9 minihunks to be chosen individually after splitting. So, I dunno. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-21 21:31 ` Junio C Hamano @ 2025-02-26 14:40 ` phillip.wood123 2025-02-26 16:49 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: phillip.wood123 @ 2025-02-26 14:40 UTC (permalink / raw) To: Junio C Hamano, Phillip Wood via GitGitGadget, Junio C Hamano Cc: git, Phillip Wood Hi Junio and Justin [I'm replying to both of you via Junio's email as you both raised the same question] On 21/02/2025 21:31, Junio C Hamano wrote: > "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > >> From: Phillip Wood <phillip.wood@dunelm.org.uk> >> >> When a hunk is split each of the new hunks inherits whether it is >> selected or not from the original hunk. This means that if a selected >> hunk is split all of the new hunks are selected and the user is not asked >> whether or not they want to select the new hunks. This is unfortunate as >> the user is presumably splitting the original hunk because they only >> want to select some sub-set of it. Fix this by marking all the new hunks >> as "undecided" so that we prompt the user to decide whether to select >> them or not. > > Good. I am very sure that the design of the current behaviour goes > back to the very original version of "add -p" with hunk splitting I > invented; I simply never considered a workflow where people may > first select and say "oops, let me take it back and redo it". What > I am getting at is that I do not think the current behaviour is > something I designed it to be with too much thought, and debeting if > it makes sense or it would be better to force them to be undecided > is probably a good thing to do now. > > Having said that, I have one small concern about forcing them to be > undecided. This now allows it to > > 1. Add the whole hunk > 2. Go back (with K) to that already chosen hunk > 3. Split > > and makes the resulting minihunks more obvious, as you do not have > to use the uppercase J/K to visit them. > > But if one is very used to do this intentionally (as opposed to > "oops, let me take it back"), this would be a usability regression. > "Ah, here is a big hunk with 10 changes, most of which I like, but > one of the lines I do not want to include" in which case I may do > the "Add the hunk to grab 10 changes, visit that decided-to-be-used > hunk, split, and then visit the one minihunk that I want to eject > and say 'n'". This makes the workflow simpler and more stupid by > requiring the 9 minihunks to be chosen individually after splitting. If the user wants to deselect the 10th mini-hunk then they have to wade through them all with or without this patch. If they want to deselect an earlier one then they will now have to do more work. Currently after a selected hunk is split we always prompt the user to make a decision on the first mini-hunk even though it is marked as selected when it is split. This seems inconsistent and confused me when I first tried splitting a selected hunk which is why I wrote this patch. I can see that in some circumstances this patch does make more work for the user, but I do think it makes it easier to understand what happens when hunk is split. Best Wishes Phillip > So, I dunno. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-26 14:40 ` phillip.wood123 @ 2025-02-26 16:49 ` Junio C Hamano 2025-02-27 16:22 ` phillip.wood123 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-02-26 16:49 UTC (permalink / raw) To: phillip.wood123; +Cc: Phillip Wood via GitGitGadget, git, Phillip Wood phillip.wood123@gmail.com writes: >> "Ah, here is a big hunk with 10 changes, most of which I like, but >> one of the lines I do not want to include" in which case I may do >> the "Add the hunk to grab 10 changes, visit that decided-to-be-used >> hunk, split, and then visit the one minihunk that I want to eject >> and say 'n'". This makes the workflow simpler and more stupid by >> requiring the 9 minihunks to be chosen individually after splitting. > > If the user wants to deselect the 10th mini-hunk then they have to > wade through them all with or without this patch. If they want to > deselect an earlier one then they will now have to do more work. Or directly jump to it with "/go-to-the-one-with-this-string"? > Currently after a selected hunk is split we always prompt the user to > make a decision on the first mini-hunk even though it is marked as > selected when it is split. This seems inconsistent and confused me > when I first tried splitting a selected hunk which is why I wrote this > patch. Hmph, so there is an obvious alternative "fix" to the inconsistency, i.e., after splitting, move to the first unselected hunk? > I can see that in some circumstances this patch does make more > work for the user, but I do think it makes it easier to understand > what happens when hunk is split. And the alternative may resolve the inconsistency and make it less work for the users? I dunno. This is totally orthogonal to this "split" issue and outside the scope of this topic, but one thing that I do not like the design of "add -p", which most likely was inherited from the very initial iteration before it was rewritten in C, is that we never ask reconfirmation once all the hunks got decided. With 3 hunks, after choosing hunk #1 by mistake, I can still go back and correct the mistake even if I noticed the mistake after making decision on the hunk #2 (thanks to the fact that hunk #3 hasn't been decided), but if the hunk #3 is missing, going back and correcting #1 becomes impossible as the program exits immediatly after deciding on #2. But I guess this depends not just on the user but on occasion. After all, re-running "reset/add -p" after such a mistake is not so huge a deal anyway. Thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-26 16:49 ` Junio C Hamano @ 2025-02-27 16:22 ` phillip.wood123 2025-02-27 18:36 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: phillip.wood123 @ 2025-02-27 16:22 UTC (permalink / raw) To: Junio C Hamano; +Cc: Phillip Wood via GitGitGadget, git, Phillip Wood On 26/02/2025 16:49, Junio C Hamano wrote: > phillip.wood123@gmail.com writes: > >>> "Ah, here is a big hunk with 10 changes, most of which I like, but >>> one of the lines I do not want to include" in which case I may do >>> the "Add the hunk to grab 10 changes, visit that decided-to-be-used >>> hunk, split, and then visit the one minihunk that I want to eject >>> and say 'n'". This makes the workflow simpler and more stupid by >>> requiring the 9 minihunks to be chosen individually after splitting. >> >> If the user wants to deselect the 10th mini-hunk then they have to >> wade through them all with or without this patch. If they want to >> deselect an earlier one then they will now have to do more work. > > Or directly jump to it with "/go-to-the-one-with-this-string"? Oh, I'd forgotten '/' searches all the hunks rather than just the undecided ones. >> Currently after a selected hunk is split we always prompt the user to >> make a decision on the first mini-hunk even though it is marked as >> selected when it is split. This seems inconsistent and confused me >> when I first tried splitting a selected hunk which is why I wrote this >> patch. > > Hmph, so there is an obvious alternative "fix" to the inconsistency, > i.e., after splitting, move to the first unselected hunk? We could do that but I think it would be even more confusing than the current behavior as it would make it harder to change the state of the mini-hunks. At least with the current behavior one can use 'J' to move through them immediately after splitting the original hunk. If we move to the next undecided hunk one has to know where the newly-created mini-hunks are relative to that. >> I can see that in some circumstances this patch does make more >> work for the user, but I do think it makes it easier to understand >> what happens when hunk is split. > > And the alternative may resolve the inconsistency and make it less > work for the users? I dunno. I'm not sure either. I dislike the way it works at the moment and find it confusing but if there are a lot of people relying on it then I'd be reluctant to change it. Unfortunately we don't have any way to know if anyone is relying on the current behavior without changing it and seeing if anyone complains. Given it is a bit of a corner case I'm not sure whether it is worth spending much more time on it. > This is totally orthogonal to this "split" issue and outside the > scope of this topic, but one thing that I do not like the design of > "add -p", which most likely was inherited from the very initial > iteration before it was rewritten in C, is that we never ask > reconfirmation once all the hunks got decided. With 3 hunks, after > choosing hunk #1 by mistake, I can still go back and correct the > mistake even if I noticed the mistake after making decision on the > hunk #2 (thanks to the fact that hunk #3 hasn't been decided), but > if the hunk #3 is missing, going back and correcting #1 becomes > impossible as the program exits immediatly after deciding on #2. > But I guess this depends not just on the user but on occasion. > After all, re-running "reset/add -p" after such a mistake is not so > huge a deal anyway. I can see the problem and asking for conformation before quitting would have been nice if we'd done it from the start. I'm not sure it is worth the disruption of changing it when one can re-run "reset/add -p" quite easily though. I guess we could add an opt-in cofing that eventually becomes the default. While we're talking about tangential issues it would be nice if when a user revisited a hunk we told them its current state. At the moment there is no way to tell if a hunk has been selected or not. Related to that the help for 'J' and 'K' talk about leaving the current hunk undecided when what they actually do is leave the current state unchanged. Best Wishes Phillip ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-27 16:22 ` phillip.wood123 @ 2025-02-27 18:36 ` Junio C Hamano 2025-02-28 16:19 ` Phillip Wood 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-02-27 18:36 UTC (permalink / raw) To: phillip.wood123; +Cc: Phillip Wood via GitGitGadget, git, Phillip Wood phillip.wood123@gmail.com writes: >>> Currently after a selected hunk is split we always prompt the user to >>> make a decision on the first mini-hunk even though it is marked as >>> selected when it is split. This seems inconsistent and confused me >>> when I first tried splitting a selected hunk which is why I wrote this >>> patch. >> Hmph, so there is an obvious alternative "fix" to the inconsistency, >> i.e., after splitting, move to the first unselected hunk? > > We could do that but I think it would be even more confusing than the > current behavior as it would make it harder to change the state of the > mini-hunks. At least with the current behavior one can use 'J' to move > through them immediately after splitting the original hunk. If we move > to the next undecided hunk one has to know where the newly-created > mini-hunks are relative to that. True. After all, going back to an already selected hunk and then splitting the hunk is a clear indication that the user wants to visit some of them to change their state. Moving them back to "undecided" (not "deselected") instead of leaving them marked as "selected" (which is the current behaviour) looks like a better behaviour and I wish I knew about the possibility in late 2006 when I added the hunk splitting. > I'm not sure either. I dislike the way it works at the moment and find > it confusing but if there are a lot of people relying on it then I'd > be reluctant to change it. I share the sentiment, especially the latter. > Unfortunately we don't have any way to know > if anyone is relying on the current behavior without changing it and > seeing if anyone complains. Given it is a bit of a corner case I'm not > sure whether it is worth spending much more time on it. Given our user base has grown quite a bit over the years, it almost is a given that any change to existing behaviour is a regression to somebody. Certainly a safe material for Git 3.0 but I do not know if it is safe enough for 2.50 for example. The strategy to leave it longer in 'next' did not work well to catch potential issues for another topic during this cycle, but we could try it out again. > I can see the problem and asking for conformation before quitting > would have been nice if we'd done it from the start. I'm not sure it > is worth the disruption of changing it when one can re-run "reset/add > -p" quite easily though. Yup. That matches my assessment of it. I brought it up because I see this "selection should not stick across splitting" falls into the same "it would have been nice if it were that way from the beginning" bucket. > I guess we could add an opt-in cofing that > eventually becomes the default. I'd prefer not to add configuration for tweaking such a small thing (this applies to "should selection stick across splitting?", too). > While we're talking about tangential issues it would be nice if when a > user revisited a hunk we told them its current state. At the moment > there is no way to tell if a hunk has been selected or not. The user came back with 'J' or 'K' probably because the hunk was skipped in their earlier navigation with 'k' or 'j', so users may be using it as a workaround, but I agree there should be an indicator for the (unselected, selected, undecided). > Related to that the help for 'J' and 'K' talk about leaving the > current hunk undecided when what they actually do is leave the > current state unchanged. Nice catch. Thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-27 18:36 ` Junio C Hamano @ 2025-02-28 16:19 ` Phillip Wood 2025-02-28 17:06 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Phillip Wood @ 2025-02-28 16:19 UTC (permalink / raw) To: Junio C Hamano; +Cc: Phillip Wood via GitGitGadget, git, Phillip Wood On 27/02/2025 18:36, Junio C Hamano wrote: > phillip.wood123@gmail.com writes: > >>>> Currently after a selected hunk is split we always prompt the user to >>>> make a decision on the first mini-hunk even though it is marked as >>>> selected when it is split. This seems inconsistent and confused me >>>> when I first tried splitting a selected hunk which is why I wrote this >>>> patch. >>> Hmph, so there is an obvious alternative "fix" to the inconsistency, >>> i.e., after splitting, move to the first unselected hunk? >> >> We could do that but I think it would be even more confusing than the >> current behavior as it would make it harder to change the state of the >> mini-hunks. At least with the current behavior one can use 'J' to move >> through them immediately after splitting the original hunk. If we move >> to the next undecided hunk one has to know where the newly-created >> mini-hunks are relative to that. > > True. After all, going back to an already selected hunk and then > splitting the hunk is a clear indication that the user wants to > visit some of them to change their state. Moving them back to > "undecided" (not "deselected") instead of leaving them marked as > "selected" (which is the current behaviour) looks like a better > behaviour and I wish I knew about the possibility in late 2006 when > I added the hunk splitting. > >> I'm not sure either. I dislike the way it works at the moment and find >> it confusing but if there are a lot of people relying on it then I'd >> be reluctant to change it. > > I share the sentiment, especially the latter. > >> Unfortunately we don't have any way to know >> if anyone is relying on the current behavior without changing it and >> seeing if anyone complains. Given it is a bit of a corner case I'm not >> sure whether it is worth spending much more time on it. > > Given our user base has grown quite a bit over the years, it almost > is a given that any change to existing behaviour is a regression to > somebody. Certainly a safe material for Git 3.0 but I do not know > if it is safe enough for 2.50 for example. The strategy to leave it > longer in 'next' did not work well to catch potential issues for > another topic during this cycle, but we could try it out again. I'll drop this patch for now. There was some talk a while ago about adding a mechanism to select "git 3.0" features at build or run time. If we add something like that I'll resubmit with this change guarded by that feature. >> I can see the problem and asking for conformation before quitting >> would have been nice if we'd done it from the start. I'm not sure it >> is worth the disruption of changing it when one can re-run "reset/add >> -p" quite easily though. > > Yup. That matches my assessment of it. I brought it up because I > see this "selection should not stick across splitting" falls into > the same "it would have been nice if it were that way from the > beginning" bucket. > >> I guess we could add an opt-in cofing that >> eventually becomes the default. > > I'd prefer not to add configuration for tweaking such a small thing > (this applies to "should selection stick across splitting?", too). Perhaps we should make the confirm-before-quitting thing a "git 3.0" feature as well? Best Wishes Phillip >> While we're talking about tangential issues it would be nice if when a >> user revisited a hunk we told them its current state. At the moment >> there is no way to tell if a hunk has been selected or not. > > The user came back with 'J' or 'K' probably because the hunk was > skipped in their earlier navigation with 'k' or 'j', so users may be > using it as a workaround, but I agree there should be an indicator > for the (unselected, selected, undecided). > >> Related to that the help for 'J' and 'K' talk about leaving the >> current hunk undecided when what they actually do is leave the >> current state unchanged. > > Nice catch. > > Thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-28 16:19 ` Phillip Wood @ 2025-02-28 17:06 ` Junio C Hamano 2025-03-04 10:25 ` Phillip Wood 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-02-28 17:06 UTC (permalink / raw) To: Phillip Wood; +Cc: Phillip Wood via GitGitGadget, git, Phillip Wood Phillip Wood <phillip.wood123@gmail.com> writes: > ... There was some talk a while ago about > adding a mechanism to select "git 3.0" features at build or run > time. If we add something like that I'll resubmit with this change > guarded by that feature. Documentation/BreakingChanges says that we can hide it behind WITH_BREAKING_CHANGES compile-time switch, and that is part of 2.49-rc0 already. The linux-breaking-changes GitHub Actions CI job runs with it defined. > Perhaps we should make the confirm-before-quitting thing a "git 3.0" > feature as well? I do not feel too strongly either way. Sometimes I wish it asked for the final confirmation after all hunks are decided. Most of the time I do not feel that way, which almost always is after saying 'q' to finish the selection. So I dunno, but my thinking right now is that I lean a bit toward negative than positive. In any case, I think we should indicate the (selected, deselected, undecided) for the current hunk the user is being asked about, which we talked about. As a workaround, we can do 'g' command to see the list of hunks and check the indicator (+/ /-) for each hunk. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/2] add -p: mark split hunks as undecided 2025-02-28 17:06 ` Junio C Hamano @ 2025-03-04 10:25 ` Phillip Wood 0 siblings, 0 replies; 27+ messages in thread From: Phillip Wood @ 2025-03-04 10:25 UTC (permalink / raw) To: Junio C Hamano; +Cc: Phillip Wood via GitGitGadget, git, Phillip Wood Hi Junio On 28/02/2025 17:06, Junio C Hamano wrote: > Phillip Wood <phillip.wood123@gmail.com> writes: > >> ... There was some talk a while ago about >> adding a mechanism to select "git 3.0" features at build or run >> time. If we add something like that I'll resubmit with this change >> guarded by that feature. > > Documentation/BreakingChanges says that we can hide it behind > WITH_BREAKING_CHANGES compile-time switch, and that is part of > 2.49-rc0 already. The linux-breaking-changes GitHub Actions CI job > runs with it defined. Thanks I'd missed that being merged. I'll re-roll with the changes in this patch guarded by WITH_BREAKING_CHANGES. >> Perhaps we should make the confirm-before-quitting thing a "git 3.0" >> feature as well? > > I do not feel too strongly either way. Sometimes I wish it asked > for the final confirmation after all hunks are decided. Most of the > time I do not feel that way, which almost always is after saying 'q' > to finish the selection. So I dunno, but my thinking right now is > that I lean a bit toward negative than positive. > > In any case, I think we should indicate the (selected, deselected, > undecided) for the current hunk the user is being asked about, which > we talked about. As a workaround, we can do 'g' command to see the > list of hunks and check the indicator (+/ /-) for each hunk. I'll try and take a look at that in the next release cycle Best Wishes Phillip ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 2/2] add-patch: update hunk splitability after editing 2025-02-21 14:57 [PATCH 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-02-21 14:57 ` [PATCH 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget @ 2025-02-21 14:57 ` Phillip Wood via GitGitGadget 2025-02-21 20:29 ` Justin Tobler 2025-02-21 21:42 ` Junio C Hamano 2025-09-15 15:29 ` [PATCH v2 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2 siblings, 2 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-02-21 14:57 UTC (permalink / raw) To: git; +Cc: Phillip Wood, Phillip Wood From: Phillip Wood <phillip.wood@dunelm.org.uk> When the users edits a hunk if they change deletion lines to context lines or vice versa then the number of hunks that the edited hunk can be split into may differ from the unedited hunk and so we need to update hunk->splittable_into. In practice users are unlikely to hit this bug as it is doubtful that a user who has edited a hunk will split it afterwards. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> --- add-patch.c | 12 +++++++++++- t/t3701-add-interactive.sh | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/add-patch.c b/add-patch.c index f44f98275cc..982745373df 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1182,19 +1182,29 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk, { struct hunk_header *header = &hunk->header; size_t i; + char ch, marker = ' '; + hunk->splittable_into = 0; header->old_count = header->new_count = 0; for (i = hunk->start; i < hunk->end; ) { - switch(normalize_marker(&s->plain.buf[i])) { + ch = normalize_marker(&s->plain.buf[i]); + switch (ch) { case '-': header->old_count++; + if (marker == ' ') + hunk->splittable_into++; + marker = ch; break; case '+': header->new_count++; + if (marker == ' ') + hunk->splittable_into++; + marker = ch; break; case ' ': header->old_count++; header->new_count++; + marker = ch; break; } diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 760f3d0d30f..cb81bfe64c8 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -1240,4 +1240,25 @@ test_expect_success 'splitting previous hunk marks split hunks as undecided' ' test_cmp expect actual ' +test_expect_success 'splitting edited hunk' ' + # Before the first hunk is edited it can be split into two + # hunks, after editing it can be split into three hunks. + + write_script fake-editor.sh <<-\EOF && + sed "s/^ c/-c/" "$1" >"$1.tmp" && + mv "$1.tmp" "$1" + EOF + + test_write_lines a b c d e f g h i j k l m n>file && + git add file && + test_write_lines A b c d E f g h i j k l M n >file && + ( + test_set_editor "$(pwd)/fake-editor.sh" && + test_write_lines e K s j y n y q | git add -p file + ) && + git cat-file blob :file >actual && + test_write_lines a b d e f g h i j k l M n >expect && + test_cmp expect actual +' + test_done -- gitgitgadget ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 2/2] add-patch: update hunk splitability after editing 2025-02-21 14:57 ` [PATCH 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget @ 2025-02-21 20:29 ` Justin Tobler 2025-02-21 21:42 ` Junio C Hamano 1 sibling, 0 replies; 27+ messages in thread From: Justin Tobler @ 2025-02-21 20:29 UTC (permalink / raw) To: Phillip Wood via GitGitGadget; +Cc: git, Phillip Wood On 25/02/21 02:57PM, Phillip Wood via GitGitGadget wrote: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > When the users edits a hunk if they change deletion lines to context > lines or vice versa then the number of hunks that the edited hunk can be > split into may differ from the unedited hunk and so we need to update > hunk->splittable_into. In practice users are unlikely to hit this bug as > it is doubtful that a user who has edited a hunk will split it > afterwards. If I'm understanding this correctly, the issue here is that, when a patch is editted, the number of hunks in can be split into may change, but is not reevaluated. This could lead to issue if the editted hunk is subsequently split. This issue would also apply to addition lines being changed to context lines as well correct? > > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> > --- > add-patch.c | 12 +++++++++++- > t/t3701-add-interactive.sh | 21 +++++++++++++++++++++ > 2 files changed, 32 insertions(+), 1 deletion(-) > > diff --git a/add-patch.c b/add-patch.c > index f44f98275cc..982745373df 100644 > --- a/add-patch.c > +++ b/add-patch.c > @@ -1182,19 +1182,29 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk, > { > struct hunk_header *header = &hunk->header; > size_t i; > + char ch, marker = ' '; > > + hunk->splittable_into = 0; > header->old_count = header->new_count = 0; > for (i = hunk->start; i < hunk->end; ) { > - switch(normalize_marker(&s->plain.buf[i])) { > + ch = normalize_marker(&s->plain.buf[i]); > + switch (ch) { > case '-': > header->old_count++; > + if (marker == ' ') > + hunk->splittable_into++; > + marker = ch; > break; > case '+': > header->new_count++; > + if (marker == ' ') > + hunk->splittable_into++; > + marker = ch; > break; > case ' ': > header->old_count++; > header->new_count++; > + marker = ch; > break; > } Ok with this we now recount the potential number of hunks a hunk can be split into. Whenever there is a change from a context line to a addition or deletion line, a separate hunk could be formed. -Justin ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/2] add-patch: update hunk splitability after editing 2025-02-21 14:57 ` [PATCH 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 2025-02-21 20:29 ` Justin Tobler @ 2025-02-21 21:42 ` Junio C Hamano 1 sibling, 0 replies; 27+ messages in thread From: Junio C Hamano @ 2025-02-21 21:42 UTC (permalink / raw) To: Phillip Wood via GitGitGadget; +Cc: git, Phillip Wood "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > When the users edits a hunk if they change deletion lines to context > lines or vice versa then the number of hunks that the edited hunk can be > split into may differ from the unedited hunk and so we need to update > hunk->splittable_into. In practice users are unlikely to hit this bug as > it is doubtful that a user who has edited a hunk will split it > afterwards. Heh, when I did the original "add -i/-p", I said "it is doubtful that a user who has selected a hunk will split it afterwards" ;-) > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> > --- > add-patch.c | 12 +++++++++++- > t/t3701-add-interactive.sh | 21 +++++++++++++++++++++ > 2 files changed, 32 insertions(+), 1 deletion(-) > > diff --git a/add-patch.c b/add-patch.c > index f44f98275cc..982745373df 100644 > --- a/add-patch.c > +++ b/add-patch.c > @@ -1182,19 +1182,29 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk, > { > struct hunk_header *header = &hunk->header; > size_t i; > + char ch, marker = ' '; > > + hunk->splittable_into = 0; > header->old_count = header->new_count = 0; > for (i = hunk->start; i < hunk->end; ) { > - switch(normalize_marker(&s->plain.buf[i])) { > + ch = normalize_marker(&s->plain.buf[i]); > + switch (ch) { > case '-': > header->old_count++; > + if (marker == ' ') > + hunk->splittable_into++; > + marker = ch; > break; > case '+': > header->new_count++; > + if (marker == ' ') > + hunk->splittable_into++; > + marker = ch; > break; > case ' ': > header->old_count++; > header->new_count++; > + marker = ch; > break; > } OK. > diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh > index 760f3d0d30f..cb81bfe64c8 100755 > --- a/t/t3701-add-interactive.sh > +++ b/t/t3701-add-interactive.sh > @@ -1240,4 +1240,25 @@ test_expect_success 'splitting previous hunk marks split hunks as undecided' ' > test_cmp expect actual > ' > > +test_expect_success 'splitting edited hunk' ' > + # Before the first hunk is edited it can be split into two > + # hunks, after editing it can be split into three hunks. > + > + write_script fake-editor.sh <<-\EOF && > + sed "s/^ c/-c/" "$1" >"$1.tmp" && > + mv "$1.tmp" "$1" > + EOF > + > + test_write_lines a b c d e f g h i j k l m n>file && > + git add file && > + test_write_lines A b c d E f g h i j k l M n >file && Missing SP before ">file" on the earlier line. > + ( > + test_set_editor "$(pwd)/fake-editor.sh" && > + test_write_lines e K s j y n y q | git add -p file > + ) && > + git cat-file blob :file >actual && > + test_write_lines a b d e f g h i j k l M n >expect && > + test_cmp expect actual > +' > + > test_done ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 0/2] add -p: a couple of hunk splitting fixes 2025-02-21 14:57 [PATCH 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-02-21 14:57 ` [PATCH 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-02-21 14:57 ` [PATCH 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget @ 2025-09-15 15:29 ` Phillip Wood via GitGitGadget 2025-09-15 15:29 ` [PATCH v2 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget ` (2 more replies) 2 siblings, 3 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-09-15 15:29 UTC (permalink / raw) To: git; +Cc: Justin Tobler, Junio C Hamano, Phillip Wood, Phillip Wood Thanks to Justin and Junio for their comments in V1. Sorry for the long delay in re-rolling - I thought I'd sent these ages ago and then discovered that they weren't upstream and realized I had not, in fact, sent them after-all. Changes since V1: * Patch 1: The new hunks created by splitting a hunk are now only marked as "undecided" when WITH_BREAKING_CHANGES is enabled. * Patch 2: Reworded commit message and added a space before a redirection in the test V1 Cover Letter: This series fixes a couple of infelicities when splitting hunks that have already been selected or edited which I noticed a while ago when preparing the test for 'pw/add-patch-with-suppress-blank-empty'. Phillip Wood (2): add -p: mark split hunks as undecided add-patch: update hunk splitability after editing Documentation/BreakingChanges.adoc | 5 +++++ add-patch.c | 19 +++++++++++++++- t/t3701-add-interactive.sh | 36 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) base-commit: 4975ec3473b4bc61bc8a3df1ef29d0b7e7959e87 Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1863%2Fphillipwood%2Fadd-p-split-hunks-are-undecided-v2 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1863/phillipwood/add-p-split-hunks-are-undecided-v2 Pull-Request: https://github.com/gitgitgadget/git/pull/1863 Range-diff vs v1: 1: 43a0592a46 ! 1: 3e2ec7b37f add -p: mark split hunks as undecided @@ Metadata ## Commit message ## add -p: mark split hunks as undecided - When a hunk is split each of the new hunks inherits whether it is - selected or not from the original hunk. This means that if a selected - hunk is split all of the new hunks are selected and the user is not asked - whether or not they want to select the new hunks. This is unfortunate as - the user is presumably splitting the original hunk because they only - want to select some sub-set of it. Fix this by marking all the new hunks - as "undecided" so that we prompt the user to decide whether to select - them or not. + When a hunk is split, each of the new hunks inherits whether it is + selected or not from the original hunk. If a selected hunk is split + all of the new hunks are marked as "selected" and the user is only + prompted with the first of the split hunks. The user is not asked + whether or not they wish to select the rest of the new hunks. This + means that if they wish to deselect any of the new hunks apart from + the first one they have to navigate back to the hunk they want to + deselect before they can deselect it. This is unfortunate as the user + is presumably splitting the original hunk because they only want to + select some sub-set of it. + + Instead mark all the new hunks as "undecided" so that the user is + prompted whether they wish to select each one in turn. In the case + where the user only wants to change the selection of the first of + the split hunks they will now have to do more work re-selecting the + remaining split hunks. However, changing the selection of any of the + other newly created hunks is now much simpler as the user no-longer has + to navigate back to them in order to change their selected state. Due + to concerns that users may be relying on the current behaviour [1] + this change is guarded by WITH_BREAKING_CHANGES. + + [1] https://lore.kernel.org/git/xmqqjz9b6xr1.fsf@gitster.g Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> + ## Documentation/BreakingChanges.adoc ## +@@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the ecosystem is ready to support the + "reftable" format. Most importantly, alternative implementations of Git like + JGit, libgit2 and Gitoxide need to support it. + ++* The behavior of "git add -p" has been changed so that splitting a ++ hunk that has already been marked as selected or unselected will now ++ prompt the user to select each of the new hunks created by the ++ split instead of them inheriting their state from the original hunk. ++ + === Removals + + * Support for grafting commits has long been superseded by git-replace(1). + ## add-patch.c ## @@ add-patch.c: static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, * sizeof(*hunk)); hunk = file_diff->hunk + hunk_index; hunk->splittable_into = 1; ++#ifdef WITH_BREAKING_CHANGES + hunk->use = UNDECIDED_HUNK; ++#endif memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); header = &hunk->header; @@ add-patch.c: next_hunk_line: hunk++; hunk->splittable_into = 1; -- hunk->use = hunk[-1].use; ++#ifdef WITH_BREAKING_CHANGES + hunk->use = UNDECIDED_HUNK; ++#else + hunk->use = hunk[-1].use; ++#endif header = &hunk->header; header->old_count = header->new_count = context_line_count; ## t/t3701-add-interactive.sh ## -@@ t/t3701-add-interactive.sh: test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' ' - test_cmp expect actual - ' +@@ t/t3701-add-interactive.sh: do + ' + done -+test_expect_success 'splitting previous hunk marks split hunks as undecided' ' ++test_expect_success WITH_BREAKING_CHANGES 'splitting previous hunk marks split hunks as undecided' ' + test_write_lines a " " b c d e f g h i j k >file && + git add file && + test_write_lines x " " b y d e f g h i j x >file && 2: 35ef0ee2b9 ! 2: 3a831b1a2d add-patch: update hunk splitability after editing @@ Metadata ## Commit message ## add-patch: update hunk splitability after editing - When the users edits a hunk if they change deletion lines to context - lines or vice versa then the number of hunks that the edited hunk can be - split into may differ from the unedited hunk and so we need to update - hunk->splittable_into. In practice users are unlikely to hit this bug as - it is doubtful that a user who has edited a hunk will split it - afterwards. + If, when the user edits a hunk, they change deletion lines into + context lines or vice versa, then the number of hunks that the edited + hunk can be split into may differ from the unedited hunk. This means + that so we should recalculate `hunk->splittable_into` after the hunk + has been edited. In practice users are unlikely to hit this bug as it + is doubtful that a user who has edited a hunk will split it afterwards. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> @@ add-patch.c: static ssize_t recount_edited_hunk(struct add_p_state *s, struct hu ## t/t3701-add-interactive.sh ## -@@ t/t3701-add-interactive.sh: test_expect_success 'splitting previous hunk marks split hunks as undecided' ' +@@ t/t3701-add-interactive.sh: test_expect_success WITH_BREAKING_CHANGES 'splitting previous hunk marks split h test_cmp expect actual ' @@ t/t3701-add-interactive.sh: test_expect_success 'splitting previous hunk marks s + mv "$1.tmp" "$1" + EOF + -+ test_write_lines a b c d e f g h i j k l m n>file && ++ test_write_lines a b c d e f g h i j k l m n >file && + git add file && + test_write_lines A b c d E f g h i j k l M n >file && + ( + test_set_editor "$(pwd)/fake-editor.sh" && -+ test_write_lines e K s j y n y q | git add -p file ++ if test_have_prereq WITH_BREAKING_CHANGES ++ then ++ test_write_lines e K s j y n y q ++ else ++ test_write_lines e K s n K n y q ++ fi | git add -p file + ) && + git cat-file blob :file >actual && + test_write_lines a b d e f g h i j k l M n >expect && -- gitgitgadget ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 1/2] add -p: mark split hunks as undecided 2025-09-15 15:29 ` [PATCH v2 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget @ 2025-09-15 15:29 ` Phillip Wood via GitGitGadget 2025-09-15 17:44 ` Junio C Hamano 2025-09-15 15:29 ` [PATCH v2 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2 siblings, 1 reply; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-09-15 15:29 UTC (permalink / raw) To: git; +Cc: Justin Tobler, Junio C Hamano, Phillip Wood, Phillip Wood, Phillip Wood From: Phillip Wood <phillip.wood@dunelm.org.uk> When a hunk is split, each of the new hunks inherits whether it is selected or not from the original hunk. If a selected hunk is split all of the new hunks are marked as "selected" and the user is only prompted with the first of the split hunks. The user is not asked whether or not they wish to select the rest of the new hunks. This means that if they wish to deselect any of the new hunks apart from the first one they have to navigate back to the hunk they want to deselect before they can deselect it. This is unfortunate as the user is presumably splitting the original hunk because they only want to select some sub-set of it. Instead mark all the new hunks as "undecided" so that the user is prompted whether they wish to select each one in turn. In the case where the user only wants to change the selection of the first of the split hunks they will now have to do more work re-selecting the remaining split hunks. However, changing the selection of any of the other newly created hunks is now much simpler as the user no-longer has to navigate back to them in order to change their selected state. Due to concerns that users may be relying on the current behaviour [1] this change is guarded by WITH_BREAKING_CHANGES. [1] https://lore.kernel.org/git/xmqqjz9b6xr1.fsf@gitster.g Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> --- Documentation/BreakingChanges.adoc | 5 +++++ add-patch.c | 7 +++++++ t/t3701-add-interactive.sh | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc index f8d2eba061..f62f75898f 100644 --- a/Documentation/BreakingChanges.adoc +++ b/Documentation/BreakingChanges.adoc @@ -165,6 +165,11 @@ A prerequisite for this change is that the ecosystem is ready to support the "reftable" format. Most importantly, alternative implementations of Git like JGit, libgit2 and Gitoxide need to support it. +* The behavior of "git add -p" has been changed so that splitting a + hunk that has already been marked as selected or unselected will now + prompt the user to select each of the new hunks created by the + split instead of them inheriting their state from the original hunk. + === Removals * Support for grafting commits has long been superseded by git-replace(1). diff --git a/add-patch.c b/add-patch.c index 302e6ba7d9..32157e31ed 100644 --- a/add-patch.c +++ b/add-patch.c @@ -956,6 +956,9 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, * sizeof(*hunk)); hunk = file_diff->hunk + hunk_index; hunk->splittable_into = 1; +#ifdef WITH_BREAKING_CHANGES + hunk->use = UNDECIDED_HUNK; +#endif memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); header = &hunk->header; @@ -1057,7 +1060,11 @@ next_hunk_line: hunk++; hunk->splittable_into = 1; +#ifdef WITH_BREAKING_CHANGES + hunk->use = UNDECIDED_HUNK; +#else hunk->use = hunk[-1].use; +#endif header = &hunk->header; header->old_count = header->new_count = context_line_count; diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 04d2a19835..43a856e0c0 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -1301,4 +1301,14 @@ do ' done +test_expect_success WITH_BREAKING_CHANGES 'splitting previous hunk marks split hunks as undecided' ' + test_write_lines a " " b c d e f g h i j k >file && + git add file && + test_write_lines x " " b y d e f g h i j x >file && + test_write_lines n K s n y q | git add -p file && + git cat-file blob :file >actual && + test_write_lines a " " b y d e f g h i j k >expect && + test_cmp expect actual +' + test_done -- gitgitgadget ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/2] add -p: mark split hunks as undecided 2025-09-15 15:29 ` [PATCH v2 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget @ 2025-09-15 17:44 ` Junio C Hamano 2025-09-16 9:36 ` Phillip Wood 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-09-15 17:44 UTC (permalink / raw) To: Phillip Wood via GitGitGadget Cc: git, Justin Tobler, Phillip Wood, Phillip Wood "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > When a hunk is split, each of the new hunks inherits whether it is > selected or not from the original hunk. If a selected hunk is split > all of the new hunks are marked as "selected" and the user is only > prompted with the first of the split hunks. The user is not asked > whether or not they wish to select the rest of the new hunks. This > means that if they wish to deselect any of the new hunks apart from > the first one they have to navigate back to the hunk they want to > deselect before they can deselect it. This is unfortunate as the user > is presumably splitting the original hunk because they only want to > select some sub-set of it. > > Instead mark all the new hunks as "undecided" so that the user is > prompted whether they wish to select each one in turn. In the case > where the user only wants to change the selection of the first of > the split hunks they will now have to do more work re-selecting the > remaining split hunks. However, changing the selection of any of the > other newly created hunks is now much simpler as the user no-longer has > to navigate back to them in order to change their selected state. That is great, but ... > Due > to concerns that users may be relying on the current behaviour [1] > this change is guarded by WITH_BREAKING_CHANGES. ... this does not really sound like a good candidate for "before version X we used to do this, but after X we no longer do so". Unless it is a mere bugfix, in which case such a change does not deserve a huge-version-bump switchover like this. On the other hand, assuming it is not a bugfix but introducing a different behaviour, where both the original and the new ones are useful depending on the situation, wouldn't it be better to give users choices at runtime instead, with a configuration variable at least, but possibly with a interactive command to choose which behaviour is used on demand? ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/2] add -p: mark split hunks as undecided 2025-09-15 17:44 ` Junio C Hamano @ 2025-09-16 9:36 ` Phillip Wood 2025-09-16 16:03 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Phillip Wood @ 2025-09-16 9:36 UTC (permalink / raw) To: Junio C Hamano, Phillip Wood via GitGitGadget Cc: git, Justin Tobler, Phillip Wood Hi Junio On 15/09/2025 18:44, Junio C Hamano wrote: > "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > >> From: Phillip Wood <phillip.wood@dunelm.org.uk> >> >> When a hunk is split, each of the new hunks inherits whether it is >> selected or not from the original hunk. If a selected hunk is split >> all of the new hunks are marked as "selected" and the user is only >> prompted with the first of the split hunks. The user is not asked >> whether or not they wish to select the rest of the new hunks. This >> means that if they wish to deselect any of the new hunks apart from >> the first one they have to navigate back to the hunk they want to >> deselect before they can deselect it. This is unfortunate as the user >> is presumably splitting the original hunk because they only want to >> select some sub-set of it. >> >> Instead mark all the new hunks as "undecided" so that the user is >> prompted whether they wish to select each one in turn. In the case >> where the user only wants to change the selection of the first of >> the split hunks they will now have to do more work re-selecting the >> remaining split hunks. However, changing the selection of any of the >> other newly created hunks is now much simpler as the user no-longer has >> to navigate back to them in order to change their selected state. > > That is great, but ... > >> Due >> to concerns that users may be relying on the current behaviour [1] >> this change is guarded by WITH_BREAKING_CHANGES. > > ... this does not really sound like a good candidate for "before > version X we used to do this, but after X we no longer do so". > > Unless it is a mere bugfix, in which case such a change does not > deserve a huge-version-bump switchover like this. To me, the current behavior is strange enough to be considered a bug but when we discussed this before you were not so sure and said [1] Given our user base has grown quite a bit over the years, it almost is a given that any change to existing behaviour is a regression to somebody. Certainly a safe material for Git 3.0 but I do not know if it is safe enough for 2.50 for example. The strategy to leave it longer in 'next' did not work well to catch potential issues for another topic during this cycle, but we could try it out again. So I re-rolled using WITH_BREAKING_CHANGES. If you're happy just to change the behavior unconditionally I can go back to V1 > On the other hand, assuming it is not a bugfix but introducing a > different behaviour, where both the original and the new ones are > useful depending on the situation, wouldn't it be better to give > users choices at runtime instead, with a configuration variable at > least, but possibly with a interactive command to choose which > behaviour is used on demand? I'm not really convinced the current behavior is that useful and it is such an esoteric use of 'add -p' that I'm not sure it makes sense to add a config setting for it. Thanks Phillip [1] https://lore.kernel.org/git/xmqqjz9b6xr1.fsf@gitster.g/ ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/2] add -p: mark split hunks as undecided 2025-09-16 9:36 ` Phillip Wood @ 2025-09-16 16:03 ` Junio C Hamano 0 siblings, 0 replies; 27+ messages in thread From: Junio C Hamano @ 2025-09-16 16:03 UTC (permalink / raw) To: Phillip Wood Cc: Phillip Wood via GitGitGadget, git, Justin Tobler, Phillip Wood Phillip Wood <phillip.wood123@gmail.com> writes: > To me, the current behavior is strange enough to be considered a bug > but when we discussed this before you were not so sure and said [1] > > Given our user base has grown quite a bit over the years, it > almost is a given that any change to existing behaviour is a > regression to somebody. Certainly a safe material for Git 3.0 > but I do not know if it is safe enough for 2.50 for example. > The strategy to leave it longer in 'next' did not work well > to catch potential issues for another topic during this cycle, > but we could try it out again. > > So I re-rolled using WITH_BREAKING_CHANGES. If you're happy just to > change the behavior unconditionally I can go back to V1 I am *NOT* happy with breaking changes. Either you cut off those who you do not believe exist because the behaviour is so strange and useless (i.e. immediate "this is a bugfix, there is no mechanism to keep the broken behaviour even for a short period"), which is much better than that from my eyes if I were to be convinced that the old behaviour is nonsense, or you support them with configuration without any future deprecation, which is also fine by me. The breaking changes mechanism is to be used only when we are convinced that the old way is nonsense, we are fairly sure that no sane user is using it, and we have concensus that the old way MUST be abandoned and any existing users MUST be retrained to use the new ways, and only to buy/give some time to these users that needs retraining. Have we got that firm sense in the community that the old behaviour qualifies for breaking change mechanism? I don't, at least not yet. >> On the other hand, assuming it is not a bugfix but introducing a >> different behaviour, where both the original and the new ones are >> useful depending on the situation, wouldn't it be better to give >> users choices at runtime instead, with a configuration variable at >> least, but possibly with a interactive command to choose which >> behaviour is used on demand? > > I'm not really convinced the current behavior is that useful and it is > such an esoteric use of 'add -p' that I'm not sure it makes sense to > add a config setting for it. If so, let's break it first and see if anybody screams. Touching the breaking changes mechanism is way too early before doing that, I think. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 2/2] add-patch: update hunk splitability after editing 2025-09-15 15:29 ` [PATCH v2 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-09-15 15:29 ` [PATCH v2 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget @ 2025-09-15 15:29 ` Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2 siblings, 0 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-09-15 15:29 UTC (permalink / raw) To: git; +Cc: Justin Tobler, Junio C Hamano, Phillip Wood, Phillip Wood, Phillip Wood From: Phillip Wood <phillip.wood@dunelm.org.uk> If, when the user edits a hunk, they change deletion lines into context lines or vice versa, then the number of hunks that the edited hunk can be split into may differ from the unedited hunk. This means that so we should recalculate `hunk->splittable_into` after the hunk has been edited. In practice users are unlikely to hit this bug as it is doubtful that a user who has edited a hunk will split it afterwards. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> --- add-patch.c | 12 +++++++++++- t/t3701-add-interactive.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/add-patch.c b/add-patch.c index 32157e31ed..0754f54a38 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1191,19 +1191,29 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk, { struct hunk_header *header = &hunk->header; size_t i; + char ch, marker = ' '; + hunk->splittable_into = 0; header->old_count = header->new_count = 0; for (i = hunk->start; i < hunk->end; ) { - switch(normalize_marker(&s->plain.buf[i])) { + ch = normalize_marker(&s->plain.buf[i]); + switch (ch) { case '-': header->old_count++; + if (marker == ' ') + hunk->splittable_into++; + marker = ch; break; case '+': header->new_count++; + if (marker == ' ') + hunk->splittable_into++; + marker = ch; break; case ' ': header->old_count++; header->new_count++; + marker = ch; break; } diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 43a856e0c0..77f99e9ecb 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -1311,4 +1311,30 @@ test_expect_success WITH_BREAKING_CHANGES 'splitting previous hunk marks split h test_cmp expect actual ' +test_expect_success 'splitting edited hunk' ' + # Before the first hunk is edited it can be split into two + # hunks, after editing it can be split into three hunks. + + write_script fake-editor.sh <<-\EOF && + sed "s/^ c/-c/" "$1" >"$1.tmp" && + mv "$1.tmp" "$1" + EOF + + test_write_lines a b c d e f g h i j k l m n >file && + git add file && + test_write_lines A b c d E f g h i j k l M n >file && + ( + test_set_editor "$(pwd)/fake-editor.sh" && + if test_have_prereq WITH_BREAKING_CHANGES + then + test_write_lines e K s j y n y q + else + test_write_lines e K s n K n y q + fi | git add -p file + ) && + git cat-file blob :file >actual && + test_write_lines a b d e f g h i j k l M n >expect && + test_cmp expect actual +' + test_done -- gitgitgadget ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v3 0/2] add -p: a couple of hunk splitting fixes 2025-09-15 15:29 ` [PATCH v2 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-09-15 15:29 ` [PATCH v2 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-09-15 15:29 ` [PATCH v2 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget @ 2025-09-25 15:10 ` Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 2 siblings, 2 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-09-25 15:10 UTC (permalink / raw) To: git; +Cc: Justin Tobler, Junio C Hamano, Phillip Wood, Phillip Wood Thanks to Junio for his comments on V2. I have removed the dependency on WITH_BREAKING_CHANGES in favor of "lets change it and see if anyone screams" Changes since V2: Remove dependency on WITH_BREAKING_CHANGES and change the behavior unconditionally. This takes us back to V1 with (hopefully) better commit messages and a style fix in the tests. V2 Cover Letter: Thanks to Justin and Junio for their comments in V1. Sorry for the long delay in re-rolling - I thought I'd sent these ages ago and then discovered that they weren't upstream and realized I had not, in fact, sent them after-all. Changes since V1: * Patch 1: The new hunks created by splitting a hunk are now only marked as "undecided" when WITH_BREAKING_CHANGES is enabled. * Patch 2: Reworded commit message and added a space before a redirection in the test V1 Cover Letter: This series fixes a couple of infelicities when splitting hunks that have already been selected or edited which I noticed a while ago when preparing the test for 'pw/add-patch-with-suppress-blank-empty'. Phillip Wood (2): add -p: mark split hunks as undecided add-patch: update hunk splitability after editing add-patch.c | 15 +++++++++++++-- t/t3701-add-interactive.sh | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) base-commit: 4975ec3473b4bc61bc8a3df1ef29d0b7e7959e87 Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1863%2Fphillipwood%2Fadd-p-split-hunks-are-undecided-v3 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1863/phillipwood/add-p-split-hunks-are-undecided-v3 Pull-Request: https://github.com/gitgitgadget/git/pull/1863 Range-diff vs v2: 1: 3e2ec7b37f ! 1: 4935dde399 add -p: mark split hunks as undecided @@ Commit message the split hunks they will now have to do more work re-selecting the remaining split hunks. However, changing the selection of any of the other newly created hunks is now much simpler as the user no-longer has - to navigate back to them in order to change their selected state. Due - to concerns that users may be relying on the current behaviour [1] - this change is guarded by WITH_BREAKING_CHANGES. - - [1] https://lore.kernel.org/git/xmqqjz9b6xr1.fsf@gitster.g + to navigate back to them in order to change their selected state. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> - ## Documentation/BreakingChanges.adoc ## -@@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the ecosystem is ready to support the - "reftable" format. Most importantly, alternative implementations of Git like - JGit, libgit2 and Gitoxide need to support it. - -+* The behavior of "git add -p" has been changed so that splitting a -+ hunk that has already been marked as selected or unselected will now -+ prompt the user to select each of the new hunks created by the -+ split instead of them inheriting their state from the original hunk. -+ - === Removals - - * Support for grafting commits has long been superseded by git-replace(1). - ## add-patch.c ## @@ add-patch.c: static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, * sizeof(*hunk)); hunk = file_diff->hunk + hunk_index; hunk->splittable_into = 1; -+#ifdef WITH_BREAKING_CHANGES + hunk->use = UNDECIDED_HUNK; -+#endif memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); header = &hunk->header; @@ add-patch.c: next_hunk_line: hunk++; hunk->splittable_into = 1; -+#ifdef WITH_BREAKING_CHANGES +- hunk->use = hunk[-1].use; + hunk->use = UNDECIDED_HUNK; -+#else - hunk->use = hunk[-1].use; -+#endif header = &hunk->header; header->old_count = header->new_count = context_line_count; @@ t/t3701-add-interactive.sh: do ' done -+test_expect_success WITH_BREAKING_CHANGES 'splitting previous hunk marks split hunks as undecided' ' ++test_expect_success 'splitting previous hunk marks split hunks as undecided' ' + test_write_lines a " " b c d e f g h i j k >file && + git add file && + test_write_lines x " " b y d e f g h i j x >file && 2: 3a831b1a2d ! 2: 390686dbb3 add-patch: update hunk splitability after editing @@ add-patch.c: static ssize_t recount_edited_hunk(struct add_p_state *s, struct hu ## t/t3701-add-interactive.sh ## -@@ t/t3701-add-interactive.sh: test_expect_success WITH_BREAKING_CHANGES 'splitting previous hunk marks split h +@@ t/t3701-add-interactive.sh: test_expect_success 'splitting previous hunk marks split hunks as undecided' ' test_cmp expect actual ' @@ t/t3701-add-interactive.sh: test_expect_success WITH_BREAKING_CHANGES 'splitting + test_write_lines A b c d E f g h i j k l M n >file && + ( + test_set_editor "$(pwd)/fake-editor.sh" && -+ if test_have_prereq WITH_BREAKING_CHANGES -+ then -+ test_write_lines e K s j y n y q -+ else -+ test_write_lines e K s n K n y q -+ fi | git add -p file ++ test_write_lines e K s j y n y q | git add -p file + ) && + git cat-file blob :file >actual && + test_write_lines a b d e f g h i j k l M n >expect && -- gitgitgadget ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v3 1/2] add -p: mark split hunks as undecided 2025-09-25 15:10 ` [PATCH v3 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget @ 2025-09-25 15:10 ` Phillip Wood via GitGitGadget 2025-09-25 18:21 ` Junio C Hamano 2025-09-25 15:10 ` [PATCH v3 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 1 sibling, 1 reply; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-09-25 15:10 UTC (permalink / raw) To: git; +Cc: Justin Tobler, Junio C Hamano, Phillip Wood, Phillip Wood, Phillip Wood From: Phillip Wood <phillip.wood@dunelm.org.uk> When a hunk is split, each of the new hunks inherits whether it is selected or not from the original hunk. If a selected hunk is split all of the new hunks are marked as "selected" and the user is only prompted with the first of the split hunks. The user is not asked whether or not they wish to select the rest of the new hunks. This means that if they wish to deselect any of the new hunks apart from the first one they have to navigate back to the hunk they want to deselect before they can deselect it. This is unfortunate as the user is presumably splitting the original hunk because they only want to select some sub-set of it. Instead mark all the new hunks as "undecided" so that the user is prompted whether they wish to select each one in turn. In the case where the user only wants to change the selection of the first of the split hunks they will now have to do more work re-selecting the remaining split hunks. However, changing the selection of any of the other newly created hunks is now much simpler as the user no-longer has to navigate back to them in order to change their selected state. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> --- add-patch.c | 3 ++- t/t3701-add-interactive.sh | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/add-patch.c b/add-patch.c index 302e6ba7d9..61f42de9ea 100644 --- a/add-patch.c +++ b/add-patch.c @@ -956,6 +956,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, * sizeof(*hunk)); hunk = file_diff->hunk + hunk_index; hunk->splittable_into = 1; + hunk->use = UNDECIDED_HUNK; memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); header = &hunk->header; @@ -1057,7 +1058,7 @@ next_hunk_line: hunk++; hunk->splittable_into = 1; - hunk->use = hunk[-1].use; + hunk->use = UNDECIDED_HUNK; header = &hunk->header; header->old_count = header->new_count = context_line_count; diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 04d2a19835..a6829fd085 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -1301,4 +1301,14 @@ do ' done +test_expect_success 'splitting previous hunk marks split hunks as undecided' ' + test_write_lines a " " b c d e f g h i j k >file && + git add file && + test_write_lines x " " b y d e f g h i j x >file && + test_write_lines n K s n y q | git add -p file && + git cat-file blob :file >actual && + test_write_lines a " " b y d e f g h i j k >expect && + test_cmp expect actual +' + test_done -- gitgitgadget ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v3 1/2] add -p: mark split hunks as undecided 2025-09-25 15:10 ` [PATCH v3 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget @ 2025-09-25 18:21 ` Junio C Hamano 2025-09-26 10:12 ` Phillip Wood 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-09-25 18:21 UTC (permalink / raw) To: Phillip Wood via GitGitGadget Cc: git, Justin Tobler, Phillip Wood, Phillip Wood "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > ... In the case > where the user only wants to change the selection of the first of > the split hunks they will now have to do more work re-selecting the > remaining split hunks. In general, that is not just "first", as you can jump ahead, or just keep typing "J" which is not all that hard, until you find the hunk you are looking for, at which point you flip its status. So I would say that it is more work if you realized a small part of the change needs to be deselected after you selected a big hunk, and want to recover by splitting this already selected big hunk and selectively deselect these small number of subhunks. If you explicitly decided not to use a hunk (instead of leaving it undecided) and then chose to split it, in order to resurrect only a few part, the end-user experience would be affected equally by this change. The user is shown each one of them and needs to select. > However, changing the selection of any of the > other newly created hunks is now much simpler as the user no-longer has > to navigate back to them in order to change their selected state. So I do not exactly buy the above argument. The traditional rule that applies when you split a hunk you have already decided what to do with, these hunks will remember your earlier decision so that you can selectively change them by going through them. The new rule says that by splitting an already decided hunk, you are discarding your earlier decision and redoing the selection from scratch. But I think the new behaviour shines in one very important point. When you are looking at a hunk, you cannot easily tell if you already chose to use the hunk or not. So if you select a hunk, navigate back with "K", and then split it with "s", you may be seeing the first minihunk. You cannot tell if that is already selected, or you need to say "y" to select it. Or if you need to say "n" to deselect it, or simply saying "j" is enough. And the new behaviour sidesteps that particular usability glitch of the selection UI. By simplifying the rule to say that splitting will cancel all the previous decisions you made on the minihunks created out of the hunk, things will become much simpler. You'll be able to view all these minihunks again and choose their fate afresh. You do not have to remember (and this is the hard part---there is no strong indication of the current selected/deselected/undecided status, unless you remember you came with "j/k" not "J/K" in which case you are looking at an undecided one) what you decided to do earlier when you look at each hunk, and the split hunks remembering your earlier decision does get in your way navigating. So I like the updated behaviour very much, but I am reluctant to pretend as if we are siding one camps of folks who think that splitting a selected hunk is done with an intention to deselect most of the minihunks most of the time, playing favors. I think that is a wrong way to frame the problem this patch solved. In any case, I no longer have problems with the updated behaviour with these two patches. Thanks for working on them. Will queue. > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> > --- > add-patch.c | 3 ++- > t/t3701-add-interactive.sh | 10 ++++++++++ > 2 files changed, 12 insertions(+), 1 deletion(-) > > diff --git a/add-patch.c b/add-patch.c > index 302e6ba7d9..61f42de9ea 100644 > --- a/add-patch.c > +++ b/add-patch.c > @@ -956,6 +956,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, > * sizeof(*hunk)); > hunk = file_diff->hunk + hunk_index; > hunk->splittable_into = 1; > + hunk->use = UNDECIDED_HUNK; > memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); > > header = &hunk->header; > @@ -1057,7 +1058,7 @@ next_hunk_line: > > hunk++; > hunk->splittable_into = 1; > - hunk->use = hunk[-1].use; > + hunk->use = UNDECIDED_HUNK; > header = &hunk->header; > > header->old_count = header->new_count = context_line_count; > diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh > index 04d2a19835..a6829fd085 100755 > --- a/t/t3701-add-interactive.sh > +++ b/t/t3701-add-interactive.sh > @@ -1301,4 +1301,14 @@ do > ' > done > > +test_expect_success 'splitting previous hunk marks split hunks as undecided' ' > + test_write_lines a " " b c d e f g h i j k >file && > + git add file && > + test_write_lines x " " b y d e f g h i j x >file && > + test_write_lines n K s n y q | git add -p file && > + git cat-file blob :file >actual && > + test_write_lines a " " b y d e f g h i j k >expect && > + test_cmp expect actual > +' > + > test_done ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v3 1/2] add -p: mark split hunks as undecided 2025-09-25 18:21 ` Junio C Hamano @ 2025-09-26 10:12 ` Phillip Wood 2025-09-26 17:37 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Phillip Wood @ 2025-09-26 10:12 UTC (permalink / raw) To: Junio C Hamano, Phillip Wood via GitGitGadget Cc: git, Justin Tobler, Phillip Wood Hi Junio On 25/09/2025 19:21, Junio C Hamano wrote: > "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > >> ... In the case >> where the user only wants to change the selection of the first of >> the split hunks they will now have to do more work re-selecting the >> remaining split hunks. > > In general, that is not just "first", as you can jump ahead, or just > keep typing "J" which is not all that hard, until you find the hunk > you are looking for, at which point you flip its status. Fair enough, I think that only applies to a single split hunk though. One you select or deselect it you can't walk though the remaining split hunks J anymore because you'll have been dumped at the next undecided hunk after entering 'y' or 'n' > [...] > So I like the updated behaviour very much, but I am reluctant to > pretend as if we are siding one camps of folks who think that > splitting a selected hunk is done with an intention to deselect most > of the minihunks most of the time, playing favors. I think that > is a wrong way to frame the problem this patch solved. > > In any case, I no longer have problems with the updated behaviour > with these two patches. Thanks for working on them. > > Will queue. Thanks, do you want a different commit message or are you happy to take them as-is? Phillip > > >> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> >> --- >> add-patch.c | 3 ++- >> t/t3701-add-interactive.sh | 10 ++++++++++ >> 2 files changed, 12 insertions(+), 1 deletion(-) >> >> diff --git a/add-patch.c b/add-patch.c >> index 302e6ba7d9..61f42de9ea 100644 >> --- a/add-patch.c >> +++ b/add-patch.c >> @@ -956,6 +956,7 @@ static int split_hunk(struct add_p_state *s, struct file_diff *file_diff, >> * sizeof(*hunk)); >> hunk = file_diff->hunk + hunk_index; >> hunk->splittable_into = 1; >> + hunk->use = UNDECIDED_HUNK; >> memset(hunk + 1, 0, (splittable_into - 1) * sizeof(*hunk)); >> >> header = &hunk->header; >> @@ -1057,7 +1058,7 @@ next_hunk_line: >> >> hunk++; >> hunk->splittable_into = 1; >> - hunk->use = hunk[-1].use; >> + hunk->use = UNDECIDED_HUNK; >> header = &hunk->header; >> >> header->old_count = header->new_count = context_line_count; >> diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh >> index 04d2a19835..a6829fd085 100755 >> --- a/t/t3701-add-interactive.sh >> +++ b/t/t3701-add-interactive.sh >> @@ -1301,4 +1301,14 @@ do >> ' >> done >> >> +test_expect_success 'splitting previous hunk marks split hunks as undecided' ' >> + test_write_lines a " " b c d e f g h i j k >file && >> + git add file && >> + test_write_lines x " " b y d e f g h i j x >file && >> + test_write_lines n K s n y q | git add -p file && >> + git cat-file blob :file >actual && >> + test_write_lines a " " b y d e f g h i j k >expect && >> + test_cmp expect actual >> +' >> + >> test_done ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v3 1/2] add -p: mark split hunks as undecided 2025-09-26 10:12 ` Phillip Wood @ 2025-09-26 17:37 ` Junio C Hamano 2025-10-08 13:51 ` Phillip Wood 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2025-09-26 17:37 UTC (permalink / raw) To: Phillip Wood Cc: Phillip Wood via GitGitGadget, git, Justin Tobler, Phillip Wood Phillip Wood <phillip.wood123@gmail.com> writes: > Hi Junio > > On 25/09/2025 19:21, Junio C Hamano wrote: >> "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: >> >>> ... In the case >>> where the user only wants to change the selection of the first of >>> the split hunks they will now have to do more work re-selecting the >>> remaining split hunks. >> In general, that is not just "first", as you can jump ahead, or just >> keep typing "J" which is not all that hard, until you find the hunk >> you are looking for, at which point you flip its status. > > Fair enough, I think that only applies to a single split hunk > though. One you select or deselect it you can't walk though the > remaining split hunks J anymore because you'll have been dumped at the > next undecided hunk after entering 'y' or 'n' If you have a single hunk for a file, you cannot split after you selected that single hunk in the first place, and the change we are discussing would not help the situation. If you have two hunks, you select one (now the other one is shown), you can "K" back to the selected one, "s"plit it, and then say 'y/n' to deal with the first of the split hunks, which would take you to that "originally second" hunk. You can "K" back again to the last of the minihunk. I think the room for improvement of the UI we are seeing is mostly outside the theme of this change under discussion, but enumerating them may help somebody pick them up as #leftoverbits in the future. * There is no way to rework with a file once you decided sel/desel on all its hunks. Even when you have multiple modified files, you cannot switch from the current file to another file whose hunks have already been decided. Perhaps introduce "Y" and "N", that allows a choice like "y" and "n", but does not auto-advance? I think the current code takes "N" and performs "n", so this would be a backward incompatible change that needs to be designed better. Perhaps when no hunks are in undecided state, show a prompt "What now?" that allows you to still navigate with "J" and "K", or go to next file? * There is no way to see what state a hunk that is on the screen is in. If you remember that you came with "j" or "k" or deciding on all hunks in another file and you are automatically taken to this file, then the hunk is undecided, but if you came here with "J" or "K", you cannot tell if you decided to select it or deselect it. Perhaps tweak the "(3/5) Stage this hunk [choices]?" prompt and give this information? The change under discussion somewhot helps the first one but only when you have at least one undecided hunk in the file. The latter problem is greatly alleviated with the change under discussion on this thread. >> So I like the updated behaviour very much, but I am reluctant to >> pretend as if we are siding one camps of folks who think that >> splitting a selected hunk is done with an intention to deselect most >> of the minihunks most of the time, playing favors. I think that >> is a wrong way to frame the problem this patch solved. >> In any case, I no longer have problems with the updated behaviour >> with these two patches. Thanks for working on them. >> Will queue. > > Thanks, do you want a different commit message or are you happy to > take them as-is? Hmph, what would an improved commit log message would say? Reword the second UI problem above and explain how this change improves the situation? Thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v3 1/2] add -p: mark split hunks as undecided 2025-09-26 17:37 ` Junio C Hamano @ 2025-10-08 13:51 ` Phillip Wood 0 siblings, 0 replies; 27+ messages in thread From: Phillip Wood @ 2025-10-08 13:51 UTC (permalink / raw) To: Junio C Hamano Cc: Phillip Wood via GitGitGadget, git, Justin Tobler, Phillip Wood On 26/09/2025 18:37, Junio C Hamano wrote: > Phillip Wood <phillip.wood123@gmail.com> writes: >> On 25/09/2025 19:21, Junio C Hamano wrote: >>> "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: >>> So I like the updated behaviour very much, but I am reluctant to >>> pretend as if we are siding one camps of folks who think that >>> splitting a selected hunk is done with an intention to deselect most >>> of the minihunks most of the time, playing favors. I think that >>> is a wrong way to frame the problem this patch solved. >>> In any case, I no longer have problems with the updated behaviour >>> with these two patches. Thanks for working on them. >>> Will queue. >> >> Thanks, do you want a different commit message or are you happy to >> take them as-is? > > Hmph, what would an improved commit log message would say? Reword > the second UI problem above and explain how this change improves the > situation? Yes. Having said that I'm about to go off the list until the middle of the week after next so maybe we should settle for what we've got. Thanks Phillip ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v3 2/2] add-patch: update hunk splitability after editing 2025-09-25 15:10 ` [PATCH v3 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget @ 2025-09-25 15:10 ` Phillip Wood via GitGitGadget 1 sibling, 0 replies; 27+ messages in thread From: Phillip Wood via GitGitGadget @ 2025-09-25 15:10 UTC (permalink / raw) To: git; +Cc: Justin Tobler, Junio C Hamano, Phillip Wood, Phillip Wood, Phillip Wood From: Phillip Wood <phillip.wood@dunelm.org.uk> If, when the user edits a hunk, they change deletion lines into context lines or vice versa, then the number of hunks that the edited hunk can be split into may differ from the unedited hunk. This means that so we should recalculate `hunk->splittable_into` after the hunk has been edited. In practice users are unlikely to hit this bug as it is doubtful that a user who has edited a hunk will split it afterwards. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> --- add-patch.c | 12 +++++++++++- t/t3701-add-interactive.sh | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/add-patch.c b/add-patch.c index 61f42de9ea..bcc2d7666f 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1185,19 +1185,29 @@ static ssize_t recount_edited_hunk(struct add_p_state *s, struct hunk *hunk, { struct hunk_header *header = &hunk->header; size_t i; + char ch, marker = ' '; + hunk->splittable_into = 0; header->old_count = header->new_count = 0; for (i = hunk->start; i < hunk->end; ) { - switch(normalize_marker(&s->plain.buf[i])) { + ch = normalize_marker(&s->plain.buf[i]); + switch (ch) { case '-': header->old_count++; + if (marker == ' ') + hunk->splittable_into++; + marker = ch; break; case '+': header->new_count++; + if (marker == ' ') + hunk->splittable_into++; + marker = ch; break; case ' ': header->old_count++; header->new_count++; + marker = ch; break; } diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index a6829fd085..13739a4582 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -1311,4 +1311,25 @@ test_expect_success 'splitting previous hunk marks split hunks as undecided' ' test_cmp expect actual ' +test_expect_success 'splitting edited hunk' ' + # Before the first hunk is edited it can be split into two + # hunks, after editing it can be split into three hunks. + + write_script fake-editor.sh <<-\EOF && + sed "s/^ c/-c/" "$1" >"$1.tmp" && + mv "$1.tmp" "$1" + EOF + + test_write_lines a b c d e f g h i j k l m n >file && + git add file && + test_write_lines A b c d E f g h i j k l M n >file && + ( + test_set_editor "$(pwd)/fake-editor.sh" && + test_write_lines e K s j y n y q | git add -p file + ) && + git cat-file blob :file >actual && + test_write_lines a b d e f g h i j k l M n >expect && + test_cmp expect actual +' + test_done -- gitgitgadget ^ permalink raw reply related [flat|nested] 27+ messages in thread
end of thread, other threads:[~2025-10-08 13:51 UTC | newest] Thread overview: 27+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-02-21 14:57 [PATCH 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-02-21 14:57 ` [PATCH 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-02-21 19:52 ` Justin Tobler 2025-02-21 21:31 ` Junio C Hamano 2025-02-26 14:40 ` phillip.wood123 2025-02-26 16:49 ` Junio C Hamano 2025-02-27 16:22 ` phillip.wood123 2025-02-27 18:36 ` Junio C Hamano 2025-02-28 16:19 ` Phillip Wood 2025-02-28 17:06 ` Junio C Hamano 2025-03-04 10:25 ` Phillip Wood 2025-02-21 14:57 ` [PATCH 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 2025-02-21 20:29 ` Justin Tobler 2025-02-21 21:42 ` Junio C Hamano 2025-09-15 15:29 ` [PATCH v2 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-09-15 15:29 ` [PATCH v2 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-09-15 17:44 ` Junio C Hamano 2025-09-16 9:36 ` Phillip Wood 2025-09-16 16:03 ` Junio C Hamano 2025-09-15 15:29 ` [PATCH v2 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 0/2] add -p: a couple of hunk splitting fixes Phillip Wood via GitGitGadget 2025-09-25 15:10 ` [PATCH v3 1/2] add -p: mark split hunks as undecided Phillip Wood via GitGitGadget 2025-09-25 18:21 ` Junio C Hamano 2025-09-26 10:12 ` Phillip Wood 2025-09-26 17:37 ` Junio C Hamano 2025-10-08 13:51 ` Phillip Wood 2025-09-25 15:10 ` [PATCH v3 2/2] add-patch: update hunk splitability after editing Phillip Wood via GitGitGadget
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).