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