5

With viewing a diff for a modified working copy, is there a way to revert the hunk under the cursor?

That is, reverse the change shown in the diff, making the changes to source-file the diff refers to.

Ideally it would refresh the diff too, although I could handle that myself.


Currently I'm navigating to the hunk using diff-goto-source, then using git-gutter:revert-hunk from the git-gutter package, however I would like to perform this inside the diff.

ideasman42
  • 8,375
  • 1
  • 28
  • 105

3 Answers3

8

If you C-cC-a (diff-apply-hunk) on a hunk which has already been applied, diff-mode will detect this and ask whether you wish to reverse that change.

You can also request this directly by passing a prefix argument to the command.

In cases where the context is insufficient to tell whether or not the patch has been applied, the latter method would be necessary.

phils
  • 48,657
  • 3
  • 76
  • 115
  • Thanks for the hint, found there is an argument to reverse `(diff-apply-hunk t)`, _(this could be used to update the answer)_ – ideasman42 Dec 20 '19 at 07:44
4

There are R in diff-mode.

R runs the command diff-reverse-direction

Reverse the direction of the diffs.

So first R and then C-c C-a to apply reversed diff.

It is possible to revert individual hunk without reversing whole diff by invoking diff-aply-hunk with prefix argument. So another solution is C-u C-c C-a.

muffinmad
  • 2,250
  • 7
  • 11
1

Adding own answer, since diff-apply-hunk didn't do exactly what I wanted.

This is a stripped down diff-apply-hunk with some modified behavior, to revert hunks without changing the context.

  • The buffer is saved after reverting.
  • The hunk is removed.
  • No new windows open.

It allows for quickly navigating over a diff and reverting hunks, without having to switch buffers and save each time.

(defun diff-apply-hunk-reverse-and-save (&optional _arg)
  "Revert the current hunk, removing it from the diff, saving the buffer immediately."
  (interactive "P")
  (diff-beginning-of-hunk t)
  (pcase-let
    (
      (`(,buf ,line-offset ,pos ,_old ,new ,switched)
        (diff-find-source-location nil t))) ;; last arg is 't for always reversed.
    (cond
      ((null line-offset)
        (error "Can't find the text to patch"))
      (switched
        (error "Patch is already removed"))
      (t ;; Apply the hunk
        (with-current-buffer buf
          (goto-char (car pos))
          (delete-region (car pos) (cdr pos))
          (insert (car new))
          (save-buffer))
        (diff-hunk-kill)))))
ideasman42
  • 8,375
  • 1
  • 28
  • 105