Re: RFE: Discard hunks during `git add -p`
On Wed, Nov 02, 2016 at 06:11:14PM -0400, Jeff King wrote: > > Being able to discard hunks (reset working copy to index contents) > > during add-p would alleviate the (quite broad) hard reset. > > As Konstantin pointed out, you can already discard interactively with > "git checkout -p". It might be nice to be able to do both in the same > run, and turn the "yes/no" decision into "yes/no/discard". > > In theory it should be easy, as the same code drives the hunk selector > for both commands. It's just a matter of which command we feed the > selected hunks to. I don't know if there would be corner cases around > hunk-editing and splitting, though. The "add" phase should never touch > the working tree file itself, so any hunks present from the initial list > should still apply cleanly during the "discard" phase. The patch is something like the one below, which worked for me in a very trivial test. I won't be surprised if there are some corner cases it's missing. At the very least, coalesce_overlapping_hunks() needs to learn about the differences between "apply" and "discard" hunks (and not coalesce them!). I don't have immediate plans for this, so if somebody wants to pick it up and run with it, be my guest. -Peff diff --git a/git-add--interactive.perl b/git-add--interactive.perl index ee3d81269..43651435a 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -109,6 +109,7 @@ my %patch_modes = ( PARTICIPLE => 'staging', FILTER => 'file-only', IS_REVERSE => 0, + DISCARD => sub { apply_patch 'apply -R', @_; }, }, 'stash' => { DIFF => 'diff-index -p HEAD', @@ -1325,6 +1326,11 @@ sub patch_update_file { my ($prev, $next, $other, $undecided, $i); $other = ''; + my $discard = exists $patch_mode_flavour{DISCARD}; + if ($discard) { + $other .= ',D'; + } + if ($num <= $ix) { $ix = 0; } @@ -1384,6 +1390,9 @@ sub patch_update_file { elsif ($line =~ /^n/i) { $hunk[$ix]{USE} = 0; } + elsif ($discard && $line =~ /^D/) { + $hunk[$ix]{USE} = -1; + } elsif ($line =~ /^a/i) { while ($ix < $num) { if (!defined $hunk[$ix]{USE}) { @@ -1539,9 +1548,12 @@ sub patch_update_file { my $n_lofs = 0; my @result = (); + my @discard = (); for (@hunk) { - if ($_->{USE}) { + if ($_->{USE} > 0) { push @result, @{$_->{TEXT}}; + } elsif ($_->{USE} < 0) { + push @discard, @{$_->{TEXT}}; } } @@ -1552,6 +1564,13 @@ sub patch_update_file { refresh(); } + if (@discard) { + my @patch = reassemble_patch($head->{TEXT}, @discard); + my $apply_routine = $patch_mode_flavour{DISCARD}; + &$apply_routine(@patch); + refresh(); + } + print "\n"; return $quit; }
Re: RFE: Discard hunks during `git add -p`
On Wed, Nov 02, 2016 at 02:46:04PM +0100, Jan Engelhardt wrote: > Current version: 2.10.2 > Example workflow: > > * I would do a global substitution across a source tree, e.g. `perl -i > -pe 's{OLD_FOO\(x\)}{NEW_BAR(x, 0)}' *.c` > * Using `git add -p`, I would verify each of the substitutions that they > make sense in their respective locations, and, based on that, > answer "y" or "n" to the interactive prompting to stage good hunks. > * When done with add-p, I would commit the so-staged hunks, > and then use `git reset --hard` to discard all changes that were > not acknowledged during add-p. > > Being able to discard hunks (reset working copy to index contents) > during add-p would alleviate the (quite broad) hard reset. As Konstantin pointed out, you can already discard interactively with "git checkout -p". It might be nice to be able to do both in the same run, and turn the "yes/no" decision into "yes/no/discard". In theory it should be easy, as the same code drives the hunk selector for both commands. It's just a matter of which command we feed the selected hunks to. I don't know if there would be corner cases around hunk-editing and splitting, though. The "add" phase should never touch the working tree file itself, so any hunks present from the initial list should still apply cleanly during the "discard" phase. -Peff
Re: RFE: Discard hunks during `git add -p`
On Wed, 2 Nov 2016 14:46:04 +0100 (CET) Jan Engelhardtwrote: > Current version: 2.10.2 > Example workflow: > > * I would do a global substitution across a source tree, e.g. `perl > -i -pe 's{OLD_FOO\(x\)}{NEW_BAR(x, 0)}' *.c` > * Using `git add -p`, I would verify each of the substitutions that > they make sense in their respective locations, and, based on that, > answer "y" or "n" to the interactive prompting to stage good hunks. > * When done with add-p, I would commit the so-staged hunks, > and then use `git reset --hard` to discard all changes that were > not acknowledged during add-p. > > Being able to discard hunks (reset working copy to index contents) > during add-p would alleviate the (quite broad) hard reset. Couldn't you just do git checkout -- . after staging your approved changes? To selectively zap uncommitted changes from your working tree, you could do git checkout --patch -- . I'm not sure overloading `git add` with a "reverse" action is a good idea. I'm actually prefer pragmatism over conceptual purity but I'm not sure the prospective gain here is clear.
RFE: Discard hunks during `git add -p`
Current version: 2.10.2 Example workflow: * I would do a global substitution across a source tree, e.g. `perl -i -pe 's{OLD_FOO\(x\)}{NEW_BAR(x, 0)}' *.c` * Using `git add -p`, I would verify each of the substitutions that they make sense in their respective locations, and, based on that, answer "y" or "n" to the interactive prompting to stage good hunks. * When done with add-p, I would commit the so-staged hunks, and then use `git reset --hard` to discard all changes that were not acknowledged during add-p. Being able to discard hunks (reset working copy to index contents) during add-p would alleviate the (quite broad) hard reset. Similar approach: * global substitution * Using `git add -p`, some hunks may warrant some more editing, doable with the "e" command. The index would be updated with the extra change, but the working copy be left as-is. * When rerunning `git add -p` in such a state, a difference is shown again for such edited spots, which I would like to discard (bring the working copy into sync with index).