git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Discussion for interactive --patch commands to get --unified support
@ 2025-04-29  9:16 Leon Michalak
  2025-04-29 16:48 ` Junio C Hamano
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Leon Michalak @ 2025-04-29  9:16 UTC (permalink / raw)
  To: git

Hi everyone!

I am a big fan of `git diff` with a custom `diff.context` setting to
increase the context lines (which also extends to other commands like
`git show` which I really like). As well as this, I am also a frequent
user of `git add --patch` (and also the other interactive `--patch`
variants such as reset).

As I've grown to use and appreciate these features even more, I have
noticed and been bothered that `git add --patch` doesn't have a (easy)
way of configuring how many context lines you see. There is a
stackoverflow post
(https://stackoverflow.com/questions/6711670/git-show-more-context-when-using-git-add-i-or-git-add-e)
which mentions you can do `GIT_DIFF_OPTS=-u<number> git add -p` which
does work however isn't very user friendly or convenient.

It would be great if it was possible to start a discussion how this
could be made better (and I would be happy to submit a patch if all is
good). Whilst brainstorming briefly, here are a few options I have
thought of that could solve this pain point, some not mutually
exclusive:
- `-U<number>/--unified=<number>` command line options to the
interactive patch commands (all builtins who call `run_add_p`)
- make `diff.context` setting extend to the interactive patch commands
(not sure how a change like this would be welcomed considering it
could change users command outputs seemingly out of nowhere)
- add an `interactive.context` setting that would work like the
existing `diff.context` setting but apply only to the interactive
patch commands

Is this feature something people would welcome, and what are your thoughts?

Thanks!

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-04-29  9:16 Discussion for interactive --patch commands to get --unified support Leon Michalak
@ 2025-04-29 16:48 ` Junio C Hamano
  2025-04-29 22:09 ` Jeff King
  2025-05-02 14:39 ` Phillip Wood
  2 siblings, 0 replies; 12+ messages in thread
From: Junio C Hamano @ 2025-04-29 16:48 UTC (permalink / raw)
  To: Leon Michalak; +Cc: git

Leon Michalak <leonmichalak6@gmail.com> writes:

> As I've grown to use and appreciate these features even more, I have
> noticed and been bothered that `git add --patch` doesn't have a (easy)
> way of configuring how many context lines you see. There is a
> stackoverflow post
> (https://stackoverflow.com/questions/6711670/git-show-more-context-when-using-git-add-i-or-git-add-e)
> which mentions you can do `GIT_DIFF_OPTS=-u<number> git add -p` which
> does work however isn't very user friendly or convenient.

If it is only to specify how many context lines to ask for the diff
machinery when preparing the initial patch that is presented in the
"add -p" UI, it should be fairly easy.

I would expect that development of such a feature would progress
roughly in the following order.

 - Define "struct add_p_opt {}" that has one "unsigned int" member,
   which is the unified context length, probably in add-interactive.h;

 - Teach add-interactive.c:run_add_p() to take an extra parameter of
   type "struct add_p_opt *opt";

 - Teach builtin/add.c to take -U<n> argument, make sure to make it
   an error when '-p' or '-i' is not given and -U<n> is.  Pass it in
   that new parameter when calling run_add_p() you modified above.

 - Do the same for builtin/{checkout,reset,stash}.c where they also
   call run_add_p().

 - Add a new command (sits next to "add untracked", "patch", "diff",
   etc.) to set -U<n> in add-interactive.c:run_add_i(), so that the
   default context length of 3 can be overridden before choosing
   "patch" or "diff" commands in "git add -i".

Because we generate diff once, and then let the end-user dice and
slice freely, without keeping track of the correspondence between
what the original diff looked like and the current diff that is a
result of end-user dicing and slicing, I think extending the context
length on demand (i.e. "I started an 'add -p' session, chose a few
hunks, edited a handful hunks, and then realized that this single
hunk I want to see a bit more context") is _significantly_ harder.
The current code structure is simply not designed for it.

It would take a significant rewrite to allow you to say "OK, let me
regenerate the diff with wider context (this is the easy part) and
find the hunk with larger context that corresponds with the hunk you
are talking about (harder)".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-04-29  9:16 Discussion for interactive --patch commands to get --unified support Leon Michalak
  2025-04-29 16:48 ` Junio C Hamano
@ 2025-04-29 22:09 ` Jeff King
  2025-04-30  8:04   ` Leon Michalak
  2025-05-02 14:33   ` Phillip Wood
  2025-05-02 14:39 ` Phillip Wood
  2 siblings, 2 replies; 12+ messages in thread
From: Jeff King @ 2025-04-29 22:09 UTC (permalink / raw)
  To: Leon Michalak; +Cc: git

On Tue, Apr 29, 2025 at 10:16:15AM +0100, Leon Michalak wrote:

> - make `diff.context` setting extend to the interactive patch commands
> (not sure how a change like this would be welcomed considering it
> could change users command outputs seemingly out of nowhere)
> - add an `interactive.context` setting that would work like the
> existing `diff.context` setting but apply only to the interactive
> patch commands

In my opinion it would be fine to respect diff.context (and probably
diff.interhunkcontext[1]) by default. Though it does change the command
output, the interactive output is by definition user-facing, so we
shouldn't be breaking scripts. And we already respect other porcelain
level config like colorizing.

I think the only reason we don't already do so is that the interactive
code is built around the plumbing commands, which conservatively avoid
various config options. So the calling code has to explicitly check the
config itself.

-Peff

[1] Looking at git_diff_ui_config(), which are all the options read by
    porcelain git-diff but not by plumbing git-diff-files, etc, there
    may be other config in the same boat. E.g., I'd guess that people
    with diff.colormoved set would appreciate seeing that effect in the
    colorized versions we show. But I think it is OK to just consider
    diff.context for now, and see if anybody ever cares enough about
    other options to look into them.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-04-29 22:09 ` Jeff King
@ 2025-04-30  8:04   ` Leon Michalak
  2025-04-30 14:40     ` Junio C Hamano
  2025-05-02 14:33   ` Phillip Wood
  1 sibling, 1 reply; 12+ messages in thread
From: Leon Michalak @ 2025-04-30  8:04 UTC (permalink / raw)
  To: git; +Cc: Jeff King, gitster

> If it is only to specify how many context lines to ask for the diff
> machinery when preparing the initial patch that is presented in the
> "add -p" UI, it should be fairly easy.

This is the intention, I personally don't have a need for changing
hunk context *during* an interactive add and as you say, this looks to
be a big task.

> I would expect that development of such a feature would progress
> roughly in the following order.

As someone who has never contributed to (or even very familiar with)
the codebase, this is very helpful and I really appreciate it!

> In my opinion it would be fine to respect diff.context (and probably
> diff.interhunkcontext[1]) by default.

I think this could work nicely and agree with this approach.

> Looking at git_diff_ui_config(), which are all the options read by
> porcelain git-diff but not by plumbing git-diff-files, etc, there
> may be other config in the same boat. E.g., I'd guess that people
> with diff.colormoved set would appreciate seeing that effect in the
> colorized versions we show.

Agreed. As you mention it, I recently discovered `diff.colormoved` and
I'd welcome this to the `--patch` functionality, although I also agree
that it would make sense to take things one step at a time and it's
not necessary to batch anything else into this change.

With all that being said, I propose the following:
- inheriting `diff.context` and `diff.interhunkcontext` as the
defaults for the various interactive/patch commands
- be able to override these defaults on the command line with
`-U<n>/--unified=<n>` and `--inter-hunk-context=<n>` respectively

These would cover both a "permanent" config that you wouldn't need to
specify every time when writing the command/s out, but also would
provide a way to override the individual built-ins as/when you want.

You guys obviously have better knowledge and experience with git
development so it would be great to hear your feedback on this.

Thanks!

On Tue, 29 Apr 2025 at 23:09, Jeff King <peff@peff.net> wrote:
>
> On Tue, Apr 29, 2025 at 10:16:15AM +0100, Leon Michalak wrote:
>
> > - make `diff.context` setting extend to the interactive patch commands
> > (not sure how a change like this would be welcomed considering it
> > could change users command outputs seemingly out of nowhere)
> > - add an `interactive.context` setting that would work like the
> > existing `diff.context` setting but apply only to the interactive
> > patch commands
>
> In my opinion it would be fine to respect diff.context (and probably
> diff.interhunkcontext[1]) by default. Though it does change the command
> output, the interactive output is by definition user-facing, so we
> shouldn't be breaking scripts. And we already respect other porcelain
> level config like colorizing.
>
> I think the only reason we don't already do so is that the interactive
> code is built around the plumbing commands, which conservatively avoid
> various config options. So the calling code has to explicitly check the
> config itself.
>
> -Peff
>
> [1] Looking at git_diff_ui_config(), which are all the options read by
>     porcelain git-diff but not by plumbing git-diff-files, etc, there
>     may be other config in the same boat. E.g., I'd guess that people
>     with diff.colormoved set would appreciate seeing that effect in the
>     colorized versions we show. But I think it is OK to just consider
>     diff.context for now, and see if anybody ever cares enough about
>     other options to look into them.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-04-30  8:04   ` Leon Michalak
@ 2025-04-30 14:40     ` Junio C Hamano
  0 siblings, 0 replies; 12+ messages in thread
From: Junio C Hamano @ 2025-04-30 14:40 UTC (permalink / raw)
  To: Leon Michalak; +Cc: git, Jeff King

Leon Michalak <leonmichalak6@gmail.com> writes:

> With all that being said, I propose the following:
> - inheriting `diff.context` and `diff.interhunkcontext` as the
> defaults for the various interactive/patch commands
> - be able to override these defaults on the command line with
> `-U<n>/--unified=<n>` and `--inter-hunk-context=<n>` respectively

I think the usage pattern when people use "add -p" and "diff" are
different (with "add -p", you get only one hunk at a time, and you
may want a bit wider context to avoid getting disoriented, for
example) and I agree that it may be useful to be able to specify
different context lengths for them, which the above should cover
nicely.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-04-29 22:09 ` Jeff King
  2025-04-30  8:04   ` Leon Michalak
@ 2025-05-02 14:33   ` Phillip Wood
  1 sibling, 0 replies; 12+ messages in thread
From: Phillip Wood @ 2025-05-02 14:33 UTC (permalink / raw)
  To: Jeff King, Leon Michalak; +Cc: git

Hi Leon and Jeff

On 29/04/2025 23:09, Jeff King wrote:
> On Tue, Apr 29, 2025 at 10:16:15AM +0100, Leon Michalak wrote:
> 
>> - make `diff.context` setting extend to the interactive patch commands
>> (not sure how a change like this would be welcomed considering it
>> could change users command outputs seemingly out of nowhere)
>> - add an `interactive.context` setting that would work like the
>> existing `diff.context` setting but apply only to the interactive
>> patch commands
> 
> In my opinion it would be fine to respect diff.context (and probably
> diff.interhunkcontext[1]) by default. Though it does change the command
> output, the interactive output is by definition user-facing, so we
> shouldn't be breaking scripts. And we already respect other porcelain
> level config like colorizing.

I think that would be a good place to start and would be a useful 
improvement on the status quo. To implement it one can copy what we do 
to respect diff.algorithm. I'm not sure it is worth the effort to 
support `git add -p -U <context>`. Being able to interactively change 
the context as suggested elsewhere sounds more interesting to me but it 
would be more work to implement as we'd have to regenerate the diff each 
time.

Best Wishes

Phillip

> I think the only reason we don't already do so is that the interactive
> code is built around the plumbing commands, which conservatively avoid
> various config options. So the calling code has to explicitly check the
> config itself.
> 
> -Peff
> 
> [1] Looking at git_diff_ui_config(), which are all the options read by
>      porcelain git-diff but not by plumbing git-diff-files, etc, there
>      may be other config in the same boat. E.g., I'd guess that people
>      with diff.colormoved set would appreciate seeing that effect in the
>      colorized versions we show. But I think it is OK to just consider
>      diff.context for now, and see if anybody ever cares enough about
>      other options to look into them.
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-04-29  9:16 Discussion for interactive --patch commands to get --unified support Leon Michalak
  2025-04-29 16:48 ` Junio C Hamano
  2025-04-29 22:09 ` Jeff King
@ 2025-05-02 14:39 ` Phillip Wood
  2025-05-02 16:14   ` Leon Michalak
  2 siblings, 1 reply; 12+ messages in thread
From: Phillip Wood @ 2025-05-02 14:39 UTC (permalink / raw)
  To: Leon Michalak, git; +Cc: Junio C Hamano, Jeff King

On 29/04/2025 10:16, Leon Michalak wrote:
> 
> (https://stackoverflow.com/questions/6711670/git-show-more-context-when-using-git-add-i-or-git-add-e)
> which mentions you can do `GIT_DIFF_OPTS=-u<number> git add -p` which
> does work however isn't very user friendly or convenient.
This is a question for others on the list rather than Leon - is it 
intentional that the plumbing diff commands respect GIT_DIFF_OPTS? If a 
script that wants to create a diff with a certain number of context 
lines runs `git diff-index -U <context>` is it helpful for that to be 
overridden if GIT_DIFF_OPTS happens to be set in the environment? 
Looking at the history it seems that environment variable used to be the 
only way to override the default context setting but that's not the case 
now.

Best Wishes

Phillip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-05-02 14:39 ` Phillip Wood
@ 2025-05-02 16:14   ` Leon Michalak
  2025-05-02 16:23     ` Leon Michalak
  2025-05-02 16:57     ` Junio C Hamano
  0 siblings, 2 replies; 12+ messages in thread
From: Leon Michalak @ 2025-05-02 16:14 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, phillip.wood

Inheriting the diff.context setting is what scratches my itch the most, although
also being able to set the context in the command list of `add -i`
sounds interesting too. Personally, I don't think I would use the
command line overrides too much myself as most of the time (like with
diff) I'd like to set the option and forget it but it does have a
certain consistency to it.

Slightly off-topic to the discussion, but does anyone have advice on
how to deal with providing a sentinel value for something like
context? I'd expect to pass `--unified` to the underlying diff command
*only* if the user specifically has overridden it via command line
option or a diff.context config, just like diff.algorithm has done,
however diff.algorithm is a `char *` so the value can be NULL which is
a good sentinel value. My thinking is then the underlying command can
just deal with the value as it sees it, such as giving a default if
not provided or making sure it's a minimum of 0 etc. Otherwise the
level above has to deal with it which then probably involves
`git_diff_ui_config` and other validations which I don't even think is
it's responsibility and would probably duplicate logic unncessarily?

I may be completely off in my assumptions here being new to the
codebase, so if anyone has any thoughts I'd greatly appreciate any
comments!

On Fri, 2 May 2025 at 15:39, Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> On 29/04/2025 10:16, Leon Michalak wrote:
> >
> > (https://stackoverflow.com/questions/6711670/git-show-more-context-when-using-git-add-i-or-git-add-e)
> > which mentions you can do `GIT_DIFF_OPTS=-u<number> git add -p` which
> > does work however isn't very user friendly or convenient.
> This is a question for others on the list rather than Leon - is it
> intentional that the plumbing diff commands respect GIT_DIFF_OPTS? If a
> script that wants to create a diff with a certain number of context
> lines runs `git diff-index -U <context>` is it helpful for that to be
> overridden if GIT_DIFF_OPTS happens to be set in the environment?
> Looking at the history it seems that environment variable used to be the
> only way to override the default context setting but that's not the case
> now.
>
> Best Wishes
>
> Phillip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-05-02 16:14   ` Leon Michalak
@ 2025-05-02 16:23     ` Leon Michalak
  2025-05-02 16:57     ` Junio C Hamano
  1 sibling, 0 replies; 12+ messages in thread
From: Leon Michalak @ 2025-05-02 16:23 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, phillip.wood

Correction to my above message, I meant to reference
`repo_diff_setup`, not `git_diff_ui_config` as that lets you
initialise a struct with the default context value that diff uses
(assuming I have understood correctly)

On Fri, 2 May 2025 at 17:14, Leon Michalak <leonmichalak6@gmail.com> wrote:
>
> Inheriting the diff.context setting is what scratches my itch the most, although
> also being able to set the context in the command list of `add -i`
> sounds interesting too. Personally, I don't think I would use the
> command line overrides too much myself as most of the time (like with
> diff) I'd like to set the option and forget it but it does have a
> certain consistency to it.
>
> Slightly off-topic to the discussion, but does anyone have advice on
> how to deal with providing a sentinel value for something like
> context? I'd expect to pass `--unified` to the underlying diff command
> *only* if the user specifically has overridden it via command line
> option or a diff.context config, just like diff.algorithm has done,
> however diff.algorithm is a `char *` so the value can be NULL which is
> a good sentinel value. My thinking is then the underlying command can
> just deal with the value as it sees it, such as giving a default if
> not provided or making sure it's a minimum of 0 etc. Otherwise the
> level above has to deal with it which then probably involves
> `git_diff_ui_config` and other validations which I don't even think is
> it's responsibility and would probably duplicate logic unncessarily?
>
> I may be completely off in my assumptions here being new to the
> codebase, so if anyone has any thoughts I'd greatly appreciate any
> comments!
>
> On Fri, 2 May 2025 at 15:39, Phillip Wood <phillip.wood123@gmail.com> wrote:
> >
> > On 29/04/2025 10:16, Leon Michalak wrote:
> > >
> > > (https://stackoverflow.com/questions/6711670/git-show-more-context-when-using-git-add-i-or-git-add-e)
> > > which mentions you can do `GIT_DIFF_OPTS=-u<number> git add -p` which
> > > does work however isn't very user friendly or convenient.
> > This is a question for others on the list rather than Leon - is it
> > intentional that the plumbing diff commands respect GIT_DIFF_OPTS? If a
> > script that wants to create a diff with a certain number of context
> > lines runs `git diff-index -U <context>` is it helpful for that to be
> > overridden if GIT_DIFF_OPTS happens to be set in the environment?
> > Looking at the history it seems that environment variable used to be the
> > only way to override the default context setting but that's not the case
> > now.
> >
> > Best Wishes
> >
> > Phillip

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-05-02 16:14   ` Leon Michalak
  2025-05-02 16:23     ` Leon Michalak
@ 2025-05-02 16:57     ` Junio C Hamano
  2025-05-02 17:13       ` Leon Michalak
  1 sibling, 1 reply; 12+ messages in thread
From: Junio C Hamano @ 2025-05-02 16:57 UTC (permalink / raw)
  To: Leon Michalak; +Cc: git, Jeff King, phillip.wood

Leon Michalak <leonmichalak6@gmail.com> writes:

> Inheriting the diff.context setting is what scratches my itch the most, although
> also being able to set the context in the command list of `add -i`
> sounds interesting too. Personally, I don't think I would use the
> command line overrides too much myself as most of the time (like with
> diff) I'd like to set the option and forget it but it does have a
> certain consistency to it.

Sounds good.

> Slightly off-topic to the discussion, but does anyone have advice on
> how to deal with providing a sentinel value for something like
> context?

Seeing in diff.c

    static int diff_context_default = 3;
    static int diff_interhunk_context_default;

that they are of signed type, and negative context would not make
sense (would it???), wouldn't -1 be a good "they haven't touched
this from the command line or configuration" value?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-05-02 16:57     ` Junio C Hamano
@ 2025-05-02 17:13       ` Leon Michalak
  2025-05-02 18:36         ` Junio C Hamano
  0 siblings, 1 reply; 12+ messages in thread
From: Leon Michalak @ 2025-05-02 17:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jeff King, phillip.wood

This is what I have been using currently although the perfectionist in
me says that a user could pass `--unified=-1` and the code would treat
that as if nothing was passed by the user.

In practice, I guess this doesn't really matter. I think that was
probably a needed sanity check, thanks

On Fri, 2 May 2025, 17:57 Junio C Hamano, <gitster@pobox.com> wrote:
>
> Leon Michalak <leonmichalak6@gmail.com> writes:
>
> > Inheriting the diff.context setting is what scratches my itch the most, although
> > also being able to set the context in the command list of `add -i`
> > sounds interesting too. Personally, I don't think I would use the
> > command line overrides too much myself as most of the time (like with
> > diff) I'd like to set the option and forget it but it does have a
> > certain consistency to it.
>
> Sounds good.
>
> > Slightly off-topic to the discussion, but does anyone have advice on
> > how to deal with providing a sentinel value for something like
> > context?
>
> Seeing in diff.c
>
>     static int diff_context_default = 3;
>     static int diff_interhunk_context_default;
>
> that they are of signed type, and negative context would not make
> sense (would it???), wouldn't -1 be a good "they haven't touched
> this from the command line or configuration" value?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Discussion for interactive --patch commands to get --unified support
  2025-05-02 17:13       ` Leon Michalak
@ 2025-05-02 18:36         ` Junio C Hamano
  0 siblings, 0 replies; 12+ messages in thread
From: Junio C Hamano @ 2025-05-02 18:36 UTC (permalink / raw)
  To: Leon Michalak; +Cc: git, Jeff King, phillip.wood

Leon Michalak <leonmichalak6@gmail.com> writes:

> This is what I have been using currently although the perfectionist in
> me says that a user could pass `--unified=-1` and the code would treat
> that as if nothing was passed by the user.

The command line parser and corresponding config parser callback can
be careful to check the value they get from the end user to avoid
that, can't they?

In any case, it is PEBKAC when the end-users do that, and they
cannot complain about their --unified=-1 are ignored.  We do not
have to care, and can just tell them "Don't do that, then."

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2025-05-02 18:36 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-29  9:16 Discussion for interactive --patch commands to get --unified support Leon Michalak
2025-04-29 16:48 ` Junio C Hamano
2025-04-29 22:09 ` Jeff King
2025-04-30  8:04   ` Leon Michalak
2025-04-30 14:40     ` Junio C Hamano
2025-05-02 14:33   ` Phillip Wood
2025-05-02 14:39 ` Phillip Wood
2025-05-02 16:14   ` Leon Michalak
2025-05-02 16:23     ` Leon Michalak
2025-05-02 16:57     ` Junio C Hamano
2025-05-02 17:13       ` Leon Michalak
2025-05-02 18:36         ` Junio C Hamano

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).