git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / Atom feed
* How to reset selected lines?
@ 2019-08-13 14:18 Pratyush Yadav
  2019-08-13 15:42 ` Jeff King
  2019-08-13 22:07 ` Johannes Sixt
  0 siblings, 2 replies; 7+ messages in thread
From: Pratyush Yadav @ 2019-08-13 14:18 UTC (permalink / raw)
  To: git

Hi,

To put things into context of why I am asking this, git-gui has a 
feature where you can select parts of a displayed diff, and can 
stage/unstage those parts. That feature is implemented in git-gui by 
just generating a diff from the selected lines, and then applying it. 
Check git-gui/lib/diff.tcl:643 for the implementation.

Now, I want to add a similar feature, but one that discards/resets the 
selected lines. And I'd like to avoid the hack that git-gui's 
apply_range_or_line is. So, is there a cleaner way to do this that does 
not involve generating a diff and then applying it?

Also, if there is a better way of staging and unstaging selected lines 
as well, do let me know, and I will try to fix git-gui's hacky way of 
doing it.

-- 
Regards,
Pratyush Yadav

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

* Re: How to reset selected lines?
  2019-08-13 14:18 How to reset selected lines? Pratyush Yadav
@ 2019-08-13 15:42 ` Jeff King
  2019-08-13 17:32   ` Junio C Hamano
  2019-08-14 11:48   ` Pratyush Yadav
  2019-08-13 22:07 ` Johannes Sixt
  1 sibling, 2 replies; 7+ messages in thread
From: Jeff King @ 2019-08-13 15:42 UTC (permalink / raw)
  To: Pratyush Yadav; +Cc: git

On Tue, Aug 13, 2019 at 07:48:16PM +0530, Pratyush Yadav wrote:

> To put things into context of why I am asking this, git-gui has a 
> feature where you can select parts of a displayed diff, and can 
> stage/unstage those parts. That feature is implemented in git-gui by 
> just generating a diff from the selected lines, and then applying it. 
> Check git-gui/lib/diff.tcl:643 for the implementation.
> 
> Now, I want to add a similar feature, but one that discards/resets the 
> selected lines. And I'd like to avoid the hack that git-gui's 
> apply_range_or_line is. So, is there a cleaner way to do this that does 
> not involve generating a diff and then applying it?

To answer your second question first:

Git's index and trees only understand whole files, so at some point you
must generate the final file content. A diff is an easy way to represent
the changes, apply them to the existing state, and then get that final
content. But it doesn't _have_ to be. You could make some modifications
to what is in the working tree and then say "OK, now stage this.".

BUT. That is probably not what the user wants, if the content in the
index actually has some modifications that are not in the working tree
(i.e., you wouldn't want to overwrite them). Hence we tend to work with
diffs, saying "make these changes to what is already in the index, and
if they conflict, then bail".

So "git add -p", for example, also works by creating diffs, modifying
them, and feeding the result to "apply". You can see the implementation
in git-add--interactive.perl, where it literally calls diff and apply
commands.

And that leads us to the answer to the first question. That script
implements "add -p", but also "checkout -p" (which is what you want),
"reset -p", "stash -p", etc. They differ only in what we diff and how we
apply the result; the main engine of slicing and dicing the diff through
user interaction is the same. See the %patch_modes hash for the list.

-Peff

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

* Re: How to reset selected lines?
  2019-08-13 15:42 ` Jeff King
@ 2019-08-13 17:32   ` Junio C Hamano
  2019-08-14 11:48   ` Pratyush Yadav
  1 sibling, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2019-08-13 17:32 UTC (permalink / raw)
  To: Jeff King; +Cc: Pratyush Yadav, git

Jeff King <peff@peff.net> writes:

> Git's index and trees only understand whole files, so at some point you
> must generate the final file content. A diff is an easy way to represent
> the changes, apply them to the existing state, and then get that final
> content. But it doesn't _have_ to be. You could make some modifications
> to what is in the working tree and then say "OK, now stage this.".
>
> BUT. That is probably not what the user wants, if the content in the
> index actually has some modifications that are not in the working tree
> (i.e., you wouldn't want to overwrite them). Hence we tend to work with
> diffs, saying "make these changes to what is already in the index, and
> if they conflict, then bail".
>
> So "git add -p", for example, also works by creating diffs, modifying
> them, and feeding the result to "apply". You can see the implementation
> in git-add--interactive.perl, where it literally calls diff and apply
> commands.
>
> And that leads us to the answer to the first question. That script
> implements "add -p", but also "checkout -p" (which is what you want),
> "reset -p", "stash -p", etc. They differ only in what we diff and how we
> apply the result; the main engine of slicing and dicing the diff through
> user interaction is the same. See the %patch_modes hash for the list.

I was about to respond but you said everything I wanted to say and
said it a lot better than I could ;-)


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

* Re: How to reset selected lines?
  2019-08-13 14:18 How to reset selected lines? Pratyush Yadav
  2019-08-13 15:42 ` Jeff King
@ 2019-08-13 22:07 ` Johannes Sixt
  2019-08-14 11:11   ` Pratyush Yadav
  1 sibling, 1 reply; 7+ messages in thread
From: Johannes Sixt @ 2019-08-13 22:07 UTC (permalink / raw)
  To: Pratyush Yadav; +Cc: git

Am 13.08.19 um 16:18 schrieb Pratyush Yadav:
> Now, I want to add a similar feature, but one that discards/resets the 
> selected lines. And I'd like to avoid the hack that git-gui's 
> apply_range_or_line is. So, is there a cleaner way to do this that does 
> not involve generating a diff and then applying it?

Don't waste your time. I'm using this feature since years. It's
available in these three commits:

https://github.com/j6t/git/commit/55276690b2bc6a
https://github.com/j6t/git/commit/f12b294b68b595
https://github.com/j6t/git/commit/00860615691604

Thanks go to Bert Wesarg. The patches are also available in this thread:

https://public-inbox.org/git/cccd6193cf3bfe170e14270204d735a842bb8563.1326116492.git.bert.wesarg@googlemail.com/#t

-- Hannes

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

* Re: How to reset selected lines?
  2019-08-13 22:07 ` Johannes Sixt
@ 2019-08-14 11:11   ` Pratyush Yadav
  0 siblings, 0 replies; 7+ messages in thread
From: Pratyush Yadav @ 2019-08-14 11:11 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git

On 14/08/19 12:07AM, Johannes Sixt wrote:
> Am 13.08.19 um 16:18 schrieb Pratyush Yadav:
> > Now, I want to add a similar feature, but one that discards/resets the 
> > selected lines. And I'd like to avoid the hack that git-gui's 
> > apply_range_or_line is. So, is there a cleaner way to do this that does 
> > not involve generating a diff and then applying it?
> 
> Don't waste your time. I'm using this feature since years. It's
> available in these three commits:
> 
> https://github.com/j6t/git/commit/55276690b2bc6a
> https://github.com/j6t/git/commit/f12b294b68b595
> https://github.com/j6t/git/commit/00860615691604
> 
> Thanks go to Bert Wesarg. The patches are also available in this thread:
> 
> https://public-inbox.org/git/cccd6193cf3bfe170e14270204d735a842bb8563.1326116492.git.bert.wesarg@googlemail.com/#t

Thanks for letting me know. I did try a similar change, before asking 
here, but git-apply complained about corrupt patches, so I thought more 
work had to be done. I'll look into the patches and see if I can work 
them into patches fit for merging.

-- 
Regards,
Pratyush Yadav

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

* Re: How to reset selected lines?
  2019-08-13 15:42 ` Jeff King
  2019-08-13 17:32   ` Junio C Hamano
@ 2019-08-14 11:48   ` Pratyush Yadav
  2019-08-14 14:52     ` Jeff King
  1 sibling, 1 reply; 7+ messages in thread
From: Pratyush Yadav @ 2019-08-14 11:48 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On 13/08/19 11:42AM, Jeff King wrote:
> On Tue, Aug 13, 2019 at 07:48:16PM +0530, Pratyush Yadav wrote:
> 
> > To put things into context of why I am asking this, git-gui has a 
> > feature where you can select parts of a displayed diff, and can 
> > stage/unstage those parts. That feature is implemented in git-gui by 
> > just generating a diff from the selected lines, and then applying it. 
> > Check git-gui/lib/diff.tcl:643 for the implementation.
> > 
> > Now, I want to add a similar feature, but one that discards/resets the 
> > selected lines. And I'd like to avoid the hack that git-gui's 
> > apply_range_or_line is. So, is there a cleaner way to do this that does 
> > not involve generating a diff and then applying it?
> 
> To answer your second question first:
> 
> Git's index and trees only understand whole files, so at some point you
> must generate the final file content. A diff is an easy way to represent
> the changes, apply them to the existing state, and then get that final
> content. But it doesn't _have_ to be. You could make some modifications
> to what is in the working tree and then say "OK, now stage this.".
> 
> BUT. That is probably not what the user wants, if the content in the
> index actually has some modifications that are not in the working tree
> (i.e., you wouldn't want to overwrite them). Hence we tend to work with
> diffs, saying "make these changes to what is already in the index, and
> if they conflict, then bail".
> 
> So "git add -p", for example, also works by creating diffs, modifying
> them, and feeding the result to "apply". You can see the implementation
> in git-add--interactive.perl, where it literally calls diff and apply
> commands.
> 
> And that leads us to the answer to the first question. That script
> implements "add -p", but also "checkout -p" (which is what you want),
> "reset -p", "stash -p", etc. They differ only in what we diff and how we
> apply the result; the main engine of slicing and dicing the diff through
> user interaction is the same. See the %patch_modes hash for the list.

Ah, so that means I do have to dive into generating diffs. Too bad, I 
was hoping for a cleaner (read: easier) way.

On that note, I don't suppose there is a way to use 
git-add--interactive's diff engine from a script, is there?  That'd 
allow me to not write potentially buggy code and solve problems someone 
already solved.

Thanks for your detailed answer.

-- 
Regards,
Pratyush Yadav

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

* Re: How to reset selected lines?
  2019-08-14 11:48   ` Pratyush Yadav
@ 2019-08-14 14:52     ` Jeff King
  0 siblings, 0 replies; 7+ messages in thread
From: Jeff King @ 2019-08-14 14:52 UTC (permalink / raw)
  To: Pratyush Yadav; +Cc: git

On Wed, Aug 14, 2019 at 05:18:44PM +0530, Pratyush Yadav wrote:

> > So "git add -p", for example, also works by creating diffs, modifying
> > them, and feeding the result to "apply". You can see the implementation
> > in git-add--interactive.perl, where it literally calls diff and apply
> > commands.
> > 
> > And that leads us to the answer to the first question. That script
> > implements "add -p", but also "checkout -p" (which is what you want),
> > "reset -p", "stash -p", etc. They differ only in what we diff and how we
> > apply the result; the main engine of slicing and dicing the diff through
> > user interaction is the same. See the %patch_modes hash for the list.
> 
> Ah, so that means I do have to dive into generating diffs. Too bad, I 
> was hoping for a cleaner (read: easier) way.
> 
> On that note, I don't suppose there is a way to use 
> git-add--interactive's diff engine from a script, is there?  That'd 
> allow me to not write potentially buggy code and solve problems someone 
> already solved.

The actual diffing is all done by lower-level commands. So I'm not sure
there's much "engine" to reuse from the script. It takes care of asking
the user about which lines to look at, how to split the diff, etc, but
that's the part you'd want a totally different interface for.

The one thing you _might_ want to pick up is the line recounting bits.
We used to just call "apply --recount", but I think there were some
corner cases that it couldn't handle well. The details are in 2b8ea7f3c7
(add -p: calculate offset delta for edited patches, 2018-03-05) and
3a8522f41f (add -p: don't rely on apply's '--recount' option,
2018-03-05), and probably some mailing list around those.

You could probably start with just not handling those corner cases,
though (either relying on "apply --recount", or just using whatever
git-gui already does now for staging).

-Peff

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

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-13 14:18 How to reset selected lines? Pratyush Yadav
2019-08-13 15:42 ` Jeff King
2019-08-13 17:32   ` Junio C Hamano
2019-08-14 11:48   ` Pratyush Yadav
2019-08-14 14:52     ` Jeff King
2019-08-13 22:07 ` Johannes Sixt
2019-08-14 11:11   ` Pratyush Yadav

git@vger.kernel.org list mirror (unofficial, one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox