mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
VC revert commands: Facilities to entirely delete revisions
* lisp/vc/vc.el (vc-revision-revert, vc-revision-cherry-pick): Rename to ... (vc-revert-or-delete-revision, vc-cherry-pick): ... these (bug#79408). All uses changed. * lisp/vc/log-view.el (log-view-revision-revert) (log-view-revision-cherry-pick): Rename to ... (log-view-revert-or-delete-revisions, log-view-cherry-pick): ... these. All uses changed. * lisp/vc/log-view.el (log-view-revert-or-delete-revisions): * lisp/vc/vc.el (vc-revert-or-delete-revision): New INTERACTIVE and DELETE parameters, and prefix argument. Offer to entirely delete REV in certain circumstances (bug#79408). * lisp/vc/log-view.el (log-view--pick-or-revert): * lisp/vc/vc.el (vc--pick-or-revert): New INTERACTIVE and DELETE parameters. All uses changes. * lisp/vc/log-view.el (log-view-revert-revisions) (log-view-delete-revisions): * lisp/vc/vc.el (vc-revert-revision, vc-delete-revision): New commands (bug#79408). * doc/emacs/maintaining.texi (VC Change Log, VC Undo) (Copying Between Branches): * etc/NEWS: Document the changes.
This commit is contained in:
parent
5dfcba699e
commit
2e8cc345d5
5 changed files with 343 additions and 94 deletions
|
|
@ -1268,11 +1268,11 @@ Unmark all marked entries (@code{log-view-unmark-all-entries}).
|
||||||
@item C
|
@item C
|
||||||
Copy changes to a currently checked out branch; either the changes from
|
Copy changes to a currently checked out branch; either the changes from
|
||||||
the revision at point, or the changes from all marked revisions
|
the revision at point, or the changes from all marked revisions
|
||||||
(@code{log-view-revision-cherry-pick}).
|
(@code{log-view-cherry-pick}).
|
||||||
|
|
||||||
@item R
|
@item R
|
||||||
Undo the effects of old revisions; either the revision at point, or all
|
Undo the effects of old revisions; either the revision at point, or all
|
||||||
marked revisions (@code{log-view-revision-revert}).
|
marked revisions (@code{log-view-revert-or-delete-revisions}).
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@vindex vc-log-show-limit
|
@vindex vc-log-show-limit
|
||||||
|
|
@ -1317,8 +1317,14 @@ also prompt for a specific VCS shell command to run for this purpose.
|
||||||
Revert the work file(s) in the current VC fileset to the last revision
|
Revert the work file(s) in the current VC fileset to the last revision
|
||||||
(@code{vc-revert}).
|
(@code{vc-revert}).
|
||||||
|
|
||||||
@item M-x vc-revision-revert
|
@item M-x vc-revert-or-delete-revision
|
||||||
Undo the effects of an older commit.
|
Undo the effects of an older commit.
|
||||||
|
|
||||||
|
@item M-x vc-revert-revision
|
||||||
|
Make a new commit which undoes the changes made by an older one.
|
||||||
|
|
||||||
|
@item M-x vc-delete-revision
|
||||||
|
Delete an unpushed commit from the revision history.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@kindex C-x v u
|
@kindex C-x v u
|
||||||
|
|
@ -1342,20 +1348,37 @@ unlocked; you must lock again to resume editing. You can also use
|
||||||
@kbd{C-x v u} to unlock a file if you lock it and then decide not to
|
@kbd{C-x v u} to unlock a file if you lock it and then decide not to
|
||||||
change it.
|
change it.
|
||||||
|
|
||||||
@findex vc-revision-revert
|
@findex vc-revert-or-delete-revision
|
||||||
@cindex reverting commits
|
@cindex reverting commits
|
||||||
To discard changes that have already been committed, by yourself or
|
To discard changes that have already been committed, by yourself or
|
||||||
someone else, you can use @w{@kbd{M-x vc-revision-revert}}. This is
|
someone else, you can use @w{@kbd{M-x vc-revert-or-delete-revision}}.
|
||||||
called @dfn{reverting} a commit. The command prompts for a revision to
|
This is called @dfn{reverting} a commit. The command prompts for a
|
||||||
revert, and then the VC backend reverts it. Most backends implement
|
revision to revert, and then the VC backend reverts it.
|
||||||
this by making a new commit which undoes the changes made by the
|
|
||||||
revision.
|
|
||||||
|
|
||||||
An alternative way to access this functionality is to the
|
Most backends implement this by making a new commit which undoes the
|
||||||
@code{log-view-revision-revert} command, bound to @kbd{R} in Log View
|
changes made by the revision. For a distributed VCS, if the commit is
|
||||||
mode buffers (@pxref{VC Change Log}). Compared to using @w{@kbd{M-x
|
one that you made and have not yet pushed, Emacs will offer to delete it
|
||||||
vc-revision revert}} directly, this can make it easier to be sure you
|
entirely, instead. With a prefix argument, this command will only try
|
||||||
are reverting the revision you intend.
|
to entirely delete the revision, failing if it has already been pushed.
|
||||||
|
|
||||||
|
An alternative way to access this functionality is the
|
||||||
|
@code{log-view-revert-or-delete-revisions} command, bound to @kbd{R} in
|
||||||
|
Log View mode buffers (@pxref{VC Change Log}). Compared to using
|
||||||
|
@w{@kbd{M-x vc-revision revert}} directly, this can make it easier to be
|
||||||
|
sure you are reverting the revision you intend.
|
||||||
|
|
||||||
|
@findex vc-revert-revision
|
||||||
|
@findex vc-delete-revision
|
||||||
|
More specific, specialized commands are @w{@kbd{M-x
|
||||||
|
vc-revert-revision}} and @w{@kbd{M-x vc-delete-revision}}. The first of
|
||||||
|
these prompts for a revision and then always makes a new commit which
|
||||||
|
undoes the changes made by that revision, regardless of the VCS in use
|
||||||
|
and whether or not the revision is pushed. The second command prompts
|
||||||
|
for a revision and then always deletes it, though it will stop if the
|
||||||
|
commit has been pushed. Usually @code{vc-revert-or-delete-revision} is
|
||||||
|
sufficient, but @code{vc-revert-revision} and @code{vc-delete-revision}
|
||||||
|
can sometimes be useful for constructing particular version control
|
||||||
|
histories.
|
||||||
|
|
||||||
@node VC Ignore
|
@node VC Ignore
|
||||||
@subsection Ignore Version Control Files
|
@subsection Ignore Version Control Files
|
||||||
|
|
@ -1889,7 +1912,7 @@ different revision with @kbd{C-u C-x v v}.
|
||||||
@subsubsection Copying Changes Made By Revisions Between Branches
|
@subsubsection Copying Changes Made By Revisions Between Branches
|
||||||
|
|
||||||
@table @kbd
|
@table @kbd
|
||||||
@item M-x vc-revision-cherry-pick
|
@item M-x vc-cherry-pick
|
||||||
Copy a single revision to branch checked out in this working tree.
|
Copy a single revision to branch checked out in this working tree.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
|
@ -1910,25 +1933,25 @@ can then cherry-pick that revision onto the feature-frozen branch in
|
||||||
order to fix the bug there, too. This is called @dfn{backporting} the
|
order to fix the bug there, too. This is called @dfn{backporting} the
|
||||||
revision, or backporting the fix.
|
revision, or backporting the fix.
|
||||||
|
|
||||||
@findex vc-revision-cherry-pick
|
@findex vc-cherry-pick
|
||||||
You can use the command @kbd{M-x vc-revision-cherry-pick} to
|
You can use the command @kbd{M-x vc-cherry-pick} to cherry-pick
|
||||||
cherry-pick revisions. It prompts for a revision to cherry-pick. It
|
revisions. It prompts for a revision to cherry-pick. It then pops up a
|
||||||
then pops up a buffer for you to edit the log message for the new
|
buffer for you to edit the log message for the new revision. Normally
|
||||||
revision. Normally the VC backend generates a log message including a
|
the VC backend generates a log message including a reference to the
|
||||||
reference to the revision you want to copy, so that the copy can be
|
revision you want to copy, so that the copy can be traced. If you wish,
|
||||||
traced. If you wish, you can delete this reference before typing
|
you can delete this reference before typing @kbd{C-c C-c} to conclude
|
||||||
@kbd{C-c C-c} to conclude the cherry-pick.
|
the cherry-pick.
|
||||||
|
|
||||||
Alternatively you can invoke the command with a prefix argument,
|
Alternatively you can invoke the command with a prefix argument,
|
||||||
i.e. @w{@kbd{C-u M-x vc-revision-cherry-pick}}. In this case the log
|
i.e. @w{@kbd{C-u M-x vc-cherry-pick}}. In this case the log message
|
||||||
message from the source revision is used unmodified, and the cherry-pick
|
from the source revision is used unmodified, and the cherry-pick happens
|
||||||
happens immediately, without popping up a buffer for log message edits.
|
immediately, without popping up a buffer for log message edits.
|
||||||
|
|
||||||
An alternative way to access this functionality is the
|
An alternative way to access this functionality is the
|
||||||
@code{log-view-revision-cherry-pick} command, bound to @kbd{C} in Log
|
@code{log-view-cherry-pick} command, bound to @kbd{C} in Log View mode
|
||||||
View mode buffers (@pxref{VC Change Log}). Compared to using
|
buffers (@pxref{VC Change Log}). Compared to using @w{@kbd{M-x
|
||||||
@w{@kbd{M-x vc-revision-cherry-pick}} directly, this can make it easier
|
vc-cherry-pick}} directly, this can make it easier to be sure you are
|
||||||
to be sure you are cherry-picking the revision you intend.
|
cherry-picking the revision you intend.
|
||||||
|
|
||||||
@ifnottex
|
@ifnottex
|
||||||
@include vc1-xtra.texi
|
@include vc1-xtra.texi
|
||||||
|
|
|
||||||
9
etc/NEWS
9
etc/NEWS
|
|
@ -2358,11 +2358,12 @@ the contents of those files.
|
||||||
|
|
||||||
+++
|
+++
|
||||||
*** New commands to cherry-pick and revert revisions.
|
*** New commands to cherry-pick and revert revisions.
|
||||||
The commands 'vc-revision-cherry-pick' and 'vc-revision-revert' let you
|
The commands 'vc-cherry-pick', 'vc-revert-or-delete-revision',
|
||||||
copy revisions between branches, and revert revisions.
|
'vc-revert-revision' and 'vc-delete-revision' let you copy revisions
|
||||||
|
between branches, revert and delete revisions.
|
||||||
From Log View buffers, you can use 'C' to cherry-pick the revision at
|
From Log View buffers, you can use 'C' to cherry-pick the revision at
|
||||||
point or all marked revisions, and 'R' to revert the revision at point
|
point or all marked revisions, and 'R' to undo the revision at point or
|
||||||
or all marked revisions.
|
all marked revisions.
|
||||||
|
|
||||||
*** New command 'log-edit-done-strip-cvs-lines'.
|
*** New command 'log-edit-done-strip-cvs-lines'.
|
||||||
This command strips all lines beginning with "CVS:" from the buffer.
|
This command strips all lines beginning with "CVS:" from the buffer.
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,8 @@
|
||||||
"w" #'log-view-copy-revision-as-kill
|
"w" #'log-view-copy-revision-as-kill
|
||||||
"TAB" #'log-view-msg-next
|
"TAB" #'log-view-msg-next
|
||||||
"<backtab>" #'log-view-msg-prev
|
"<backtab>" #'log-view-msg-prev
|
||||||
"C" #'log-view-revision-cherry-pick
|
"C" #'log-view-cherry-pick
|
||||||
"R" #'log-view-revision-revert)
|
"R" #'log-view-revert-or-delete-revisions)
|
||||||
|
|
||||||
(easy-menu-define log-view-mode-menu log-view-mode-map
|
(easy-menu-define log-view-mode-menu log-view-mode-map
|
||||||
"Log-View Display Menu."
|
"Log-View Display Menu."
|
||||||
|
|
@ -165,9 +165,9 @@
|
||||||
["Toggle Details at Point" log-view-toggle-entry-display
|
["Toggle Details at Point" log-view-toggle-entry-display
|
||||||
:active log-view-expanded-log-entry-function]
|
:active log-view-expanded-log-entry-function]
|
||||||
"-----"
|
"-----"
|
||||||
["Cherry-Pick Revision(s)" log-view-revision-cherry-pick
|
["Cherry-Pick Revision(s)" log-view-cherry-pick
|
||||||
:help "Copy changes from revision(s) to a branch"]
|
:help "Copy changes from revision(s) to a branch"]
|
||||||
["Revert Revision(s)" log-view-revision-revert
|
["Revert Revision(s)" log-view-revert-or-delete-revisions
|
||||||
:help "Undo the effects of old revision(s)"]
|
:help "Undo the effects of old revision(s)"]
|
||||||
"-----"
|
"-----"
|
||||||
["Next Log Entry" log-view-msg-next
|
["Next Log Entry" log-view-msg-next
|
||||||
|
|
@ -703,7 +703,8 @@ If called interactively, annotate the version at point."
|
||||||
(defvar vc-log-short-style)
|
(defvar vc-log-short-style)
|
||||||
(declare-function vc-print-log-internal "vc")
|
(declare-function vc-print-log-internal "vc")
|
||||||
|
|
||||||
(defun log-view--pick-or-revert (directory no-comment reverse)
|
(defun log-view--pick-or-revert
|
||||||
|
(directory no-comment reverse interactive delete)
|
||||||
"Copy changes from revision at point or all marked revisions.
|
"Copy changes from revision at point or all marked revisions.
|
||||||
DIRECTORY is the destination, the root of the target working tree.
|
DIRECTORY is the destination, the root of the target working tree.
|
||||||
NO-COMMENT non-nil means use the log messages of the revisions
|
NO-COMMENT non-nil means use the log messages of the revisions
|
||||||
|
|
@ -711,12 +712,15 @@ unmodified, instead of using the backend's default cherry-pick comment
|
||||||
for that revision.
|
for that revision.
|
||||||
NO-COMMENT non-nil with zero or one revisions marked also means don't
|
NO-COMMENT non-nil with zero or one revisions marked also means don't
|
||||||
prompt to edit the log message.
|
prompt to edit the log message.
|
||||||
REVERSE non-nil means to make commit(s) undoing the effects of the
|
REVERSE non-nil means to undo the effects of the revisions, instead.
|
||||||
revisions, instead."
|
INTERACTIVE and DELETE are passed on to `vc--pick-or-revert', except
|
||||||
|
additionally if INTERACTIVE is non-nil and `vc--pick-or-revert' returns
|
||||||
|
`deleted', pass `no-confirm' to subsequent calls to that function."
|
||||||
(let ((default-directory directory)
|
(let ((default-directory directory)
|
||||||
(marked (log-view-get-marked)))
|
(marked (log-view-get-marked))
|
||||||
|
(buf (current-buffer)))
|
||||||
(if (length> marked 1)
|
(if (length> marked 1)
|
||||||
(progn
|
(let ((deleted 0))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(dolist (rev (if reverse (reverse marked) marked))
|
(dolist (rev (if reverse (reverse marked) marked))
|
||||||
;; Unmark each revision *before* copying it.
|
;; Unmark each revision *before* copying it.
|
||||||
|
|
@ -724,38 +728,48 @@ revisions, instead."
|
||||||
;; fails, after resolving that conflict and committing the
|
;; fails, after resolving that conflict and committing the
|
||||||
;; cherry-pick, the right revisions will be marked to
|
;; cherry-pick, the right revisions will be marked to
|
||||||
;; resume the original multiple cherry-pick operation.
|
;; resume the original multiple cherry-pick operation.
|
||||||
|
;; FIXME: This doesn't work so long as the backend
|
||||||
|
;; functions just give up completely if there is a
|
||||||
|
;; conflict (which behavior is also a FIXME). Then in
|
||||||
|
;; fact the user has to mark the revision again.
|
||||||
(log-view-goto-rev rev)
|
(log-view-goto-rev rev)
|
||||||
(log-view-unmark-entry 1)
|
(log-view-unmark-entry 1)
|
||||||
(vc--pick-or-revert rev
|
(cl-case
|
||||||
reverse
|
(vc--pick-or-revert rev reverse interactive delete
|
||||||
(if no-comment
|
(if no-comment
|
||||||
(vc-call-backend log-view-vc-backend
|
(vc-call-backend log-view-vc-backend
|
||||||
'get-change-comment
|
'get-change-comment
|
||||||
nil rev)
|
nil rev)
|
||||||
t)
|
t)
|
||||||
nil
|
nil
|
||||||
log-view-vc-backend)))
|
log-view-vc-backend)
|
||||||
(when (vc-find-backend-function log-view-vc-backend
|
(deleted (incf deleted)
|
||||||
'modify-change-comment)
|
(when interactive
|
||||||
(let (vc-log-short-style)
|
(setq interactive 'no-confirm))))))
|
||||||
(vc-print-log-internal log-view-vc-backend
|
(let ((new-commits (- (length marked) deleted)))
|
||||||
(list default-directory)
|
(when (and (plusp new-commits)
|
||||||
nil nil (length marked)))
|
(vc-find-backend-function log-view-vc-backend
|
||||||
(setq-local vc-log-short-style nil ; For \\`g'.
|
'modify-change-comment))
|
||||||
vc-parent-buffer-name nil)
|
(let (vc-log-short-style)
|
||||||
(message (substitute-command-keys "Use \
|
(vc-print-log-internal log-view-vc-backend
|
||||||
\\[log-view-modify-change-comment] to modify any of these messages"))))
|
(list default-directory)
|
||||||
|
nil nil new-commits))
|
||||||
|
(setq-local vc-log-short-style nil ; For \\`g'.
|
||||||
|
vc-parent-buffer-name nil)
|
||||||
|
(message (substitute-command-keys "Use \
|
||||||
|
\\[log-view-modify-change-comment] to modify any of these messages")))))
|
||||||
(let ((rev (or (car marked) (log-view-current-tag))))
|
(let ((rev (or (car marked) (log-view-current-tag))))
|
||||||
(vc--pick-or-revert rev
|
(vc--pick-or-revert rev reverse interactive delete
|
||||||
reverse
|
|
||||||
(and no-comment
|
(and no-comment
|
||||||
(vc-call-backend log-view-vc-backend
|
(vc-call-backend log-view-vc-backend
|
||||||
'get-change-comment
|
'get-change-comment
|
||||||
nil rev))
|
nil rev))
|
||||||
nil
|
nil
|
||||||
log-view-vc-backend)))))
|
log-view-vc-backend)))
|
||||||
|
(when (eq (current-buffer) buf)
|
||||||
|
(revert-buffer))))
|
||||||
|
|
||||||
(defun log-view-revision-cherry-pick (directory &optional no-comment)
|
(defun log-view-cherry-pick (directory &optional no-comment)
|
||||||
"Copy changes from revision at point to current branch.
|
"Copy changes from revision at point to current branch.
|
||||||
If there are marked revisions, use those instead of the revision at point.
|
If there are marked revisions, use those instead of the revision at point.
|
||||||
|
|
||||||
|
|
@ -774,31 +788,90 @@ traced. With optional argument NO-COMMENT non-nil (interactively, with
|
||||||
a prefix argument), use the log messages from the source revisions
|
a prefix argument), use the log messages from the source revisions
|
||||||
unmodified.
|
unmodified.
|
||||||
|
|
||||||
See also `vc-revision-cherry-pick'."
|
See also `vc-cherry-pick'."
|
||||||
(interactive
|
(interactive
|
||||||
(list (vc--prompt-other-working-tree log-view-vc-backend
|
(list (vc--prompt-other-working-tree log-view-vc-backend
|
||||||
"Cherry-pick to working tree"
|
"Cherry-pick to working tree"
|
||||||
'allow-empty)
|
'allow-empty)
|
||||||
current-prefix-arg))
|
current-prefix-arg))
|
||||||
(log-view--pick-or-revert directory no-comment nil))
|
(log-view--pick-or-revert directory no-comment nil nil nil))
|
||||||
|
|
||||||
(defun log-view-revision-revert (directory)
|
(defun log-view-revert-or-delete-revisions
|
||||||
|
(directory &optional interactive delete)
|
||||||
"Undo the effects of the revision at point.
|
"Undo the effects of the revision at point.
|
||||||
When revisions are marked, undo the effects of each of them.
|
When revisions are marked, undo the effects of each of them.
|
||||||
When called interactively, prompts for the target working tree in which
|
When called interactively, prompts for the target working tree in which
|
||||||
to revert; the current working tree is the default choice.
|
to revert; the current working tree is the default choice.
|
||||||
When called from Lisp, DIRECTORY is the root of the target working tree.
|
When called from Lisp, DIRECTORY is the root of the target working tree.
|
||||||
|
|
||||||
|
When called interactively (or with optional argument INTERACTIVE
|
||||||
|
non-nil), then if the underlying VCS is distributed, offer to entirely
|
||||||
|
delete revisions that have not been pushed.
|
||||||
|
This is instead of creating new commits undoing their effects.
|
||||||
|
|
||||||
|
With a prefix argument (or with optional argument DELETE non-nil),
|
||||||
|
always delete revisions and never create new commits.
|
||||||
|
In this case INTERACTIVE is ignored.
|
||||||
|
This works only for unpublished commits, unless you have customized
|
||||||
|
`vc-allow-rewriting-published-history' to a non-nil value.
|
||||||
|
|
||||||
When reverting a single revision, prompts for editing the log message
|
When reverting a single revision, prompts for editing the log message
|
||||||
for the new commit.
|
for the new commit.
|
||||||
When reverting multiple revisions, never prompts to edit log messages.
|
When reverting multiple revisions, never prompts to edit log messages.
|
||||||
|
|
||||||
See also `vc-revision-revert'."
|
See also `vc-revert-or-delete-revision'."
|
||||||
|
(interactive (list (vc--prompt-other-working-tree
|
||||||
|
(vc-responsible-backend default-directory)
|
||||||
|
(if current-prefix-arg "Delete in working tree"
|
||||||
|
"Revert in working tree")
|
||||||
|
'allow-empty)
|
||||||
|
t current-prefix-arg))
|
||||||
|
(log-view--pick-or-revert directory nil t interactive delete))
|
||||||
|
|
||||||
|
;; These are left unbound by default. A user who doesn't like the DWIM
|
||||||
|
;; behavior of `log-view-revert-or-delete-revisions' can unbind that and
|
||||||
|
;; bind these two commands instead.
|
||||||
|
|
||||||
|
(defun log-view-revert-revisions (directory)
|
||||||
|
"Make a commit undoing the effects of the revision at point.
|
||||||
|
When revisions are marked, make such a commit for each of them.
|
||||||
|
When called interactively, prompts for the target working tree in which
|
||||||
|
to make new commits; the current working tree is the default choice.
|
||||||
|
When called from Lisp, DIRECTORY is the root of the target working tree.
|
||||||
|
|
||||||
|
This is like `log-view-revert-or-delete-revisions' except that it only
|
||||||
|
ever makes new commits undoing the effects of revisions, instead of
|
||||||
|
considering VCS-specific alternative mechanisms to undo the effects of
|
||||||
|
revisions.
|
||||||
|
|
||||||
|
When reverting a single revision, prompts for editing the log message
|
||||||
|
for the new commit.
|
||||||
|
When reverting multiple revisions, never prompts to edit log messages.
|
||||||
|
|
||||||
|
See also `vc-revert-revision'."
|
||||||
(interactive (list (vc--prompt-other-working-tree
|
(interactive (list (vc--prompt-other-working-tree
|
||||||
(vc-responsible-backend default-directory)
|
(vc-responsible-backend default-directory)
|
||||||
"Revert in working tree"
|
"Revert in working tree"
|
||||||
'allow-empty)))
|
'allow-empty)))
|
||||||
(log-view--pick-or-revert directory nil t))
|
(log-view--pick-or-revert directory nil t nil 'never))
|
||||||
|
|
||||||
|
(defun log-view-delete-revisions (directory)
|
||||||
|
"Delete the revision at point from the revision history.
|
||||||
|
When revisions are marked, delete all of them.
|
||||||
|
When called interactively, prompts for the target working tree in which
|
||||||
|
to delete revisions; the current working tree is the default choice.
|
||||||
|
When called from Lisp, DIRECTORY is the root of the target working tree.
|
||||||
|
|
||||||
|
This works only for unpublished commits, unless you have customized
|
||||||
|
`vc-allow-rewriting-published-history' to a non-nil value.
|
||||||
|
|
||||||
|
This is the same as `log-view-revert-or-delete-revisions' invoked
|
||||||
|
interactively with a prefix argument. See also `vc-delete-revision'."
|
||||||
|
(interactive (list (vc--prompt-other-working-tree
|
||||||
|
(vc-responsible-backend default-directory)
|
||||||
|
"Delete in working tree"
|
||||||
|
'allow-empty)))
|
||||||
|
(log-view--pick-or-revert directory nil t nil t))
|
||||||
|
|
||||||
;;;;
|
;;;;
|
||||||
;;;; diff
|
;;;; diff
|
||||||
|
|
|
||||||
|
|
@ -1053,11 +1053,11 @@ other commands receive global bindings where they had none before."
|
||||||
|
|
||||||
(defvar vc-menu-map
|
(defvar vc-menu-map
|
||||||
(let ((map (make-sparse-keymap "Version Control")))
|
(let ((map (make-sparse-keymap "Version Control")))
|
||||||
(define-key map [vc-revision-revert]
|
(define-key map [vc-revert-or-delete-revision]
|
||||||
'(menu-item "Revert Revision" vc-revision-revert
|
'(menu-item "Revert Revision" vc-revert-or-delete-revision
|
||||||
:help "Undo the effects of a revision"))
|
:help "Undo the effects of a revision"))
|
||||||
(define-key map [vc-revision-cherry-pick]
|
(define-key map [vc-cherry-pick]
|
||||||
'(menu-item "Cherry-Pick Revision" vc-revision-cherry-pick
|
'(menu-item "Cherry-Pick Revision" vc-cherry-pick
|
||||||
:help "Copy the changes from a single revision to this branch"))
|
:help "Copy the changes from a single revision to this branch"))
|
||||||
(define-key map [separator1] menu-bar-separator)
|
(define-key map [separator1] menu-bar-separator)
|
||||||
(define-key map [vc-retrieve-tag]
|
(define-key map [vc-retrieve-tag]
|
||||||
|
|
|
||||||
190
lisp/vc/vc.el
190
lisp/vc/vc.el
|
|
@ -2166,22 +2166,121 @@ have changed; continue with old fileset?" (current-buffer))))
|
||||||
(declare-function diff-buffer-file-names "diff-mode")
|
(declare-function diff-buffer-file-names "diff-mode")
|
||||||
(declare-function diff-reverse-direction "diff-mode")
|
(declare-function diff-reverse-direction "diff-mode")
|
||||||
|
|
||||||
(defun vc--pick-or-revert (rev reverse comment initial-contents backend)
|
(defun vc--pick-or-revert
|
||||||
|
(rev reverse interactive delete comment initial-contents backend)
|
||||||
"Copy a single revision REV to branch checked out in this working tree.
|
"Copy a single revision REV to branch checked out in this working tree.
|
||||||
REVERSE means to undo the effects of REV, instead.
|
|
||||||
|
REVERSE non-nil means to undo the effects of REV, instead.
|
||||||
|
This is affected by whether the VCS is centralized or distributed and
|
||||||
|
the INTERACTIVE and DELETE arguments, as follows:
|
||||||
|
- For a centralized VCS for which Emacs knows how to do true undos, then
|
||||||
|
unless DELETE is the special value `never', do a true undo of REV.
|
||||||
|
This function supports creating new commits undoing the effects of REV
|
||||||
|
for even a centralized VCS with true undos by passing `never' as
|
||||||
|
DELETE (as `vc-revert-revision' does).
|
||||||
|
For centralized VCS, INTERACTIVE is ignored.
|
||||||
|
- For a distributed VCS, when INTERACTIVE is non-nil, DELETE is nil, and
|
||||||
|
REV has not yet been pushed, offer to delete REV entirely instead of
|
||||||
|
creating a new commit undoing its EFFECTS.
|
||||||
|
If INTERACTIVE is `no-confirm', don't prompt to confirm the deletion.
|
||||||
|
- For a distributed VCS, when DELETE is non-nil (but not `never'), only
|
||||||
|
consider deleting REV, never create a new commit, but subject to
|
||||||
|
`vc-allow-rewriting-published-history'.
|
||||||
|
In this case INTERACTIVE is ignored.
|
||||||
|
(This complex calling convention makes for simple usage of this
|
||||||
|
workhorse function from the frontend VC commands that provide access to
|
||||||
|
all this functionality.)
|
||||||
|
|
||||||
COMMENT is a comment string; if omitted, a buffer is popped up to accept
|
COMMENT is a comment string; if omitted, a buffer is popped up to accept
|
||||||
a comment. If INITIAL-CONTENTS is non-nil, then COMMENT is used as the
|
a comment. If INITIAL-CONTENTS is non-nil, then COMMENT is used as the
|
||||||
initial contents of the log entry buffer. If COMMENT is t then use
|
initial contents of the log entry buffer. If COMMENT is t then use
|
||||||
BACKEND's default cherry-pick comment for REV without prompting.
|
BACKEND's default cherry-pick comment for REV without prompting.
|
||||||
BACKEND is the VC backend to use."
|
BACKEND is the VC backend to use.
|
||||||
(let* ((backend (or backend (vc-responsible-backend default-directory)))
|
|
||||||
;; `vc-*-prepare-patch' will always give us a patch with file
|
Return `deleted' if we actually undid/deleted a commit.
|
||||||
;; names relative to the VC root, so switch to there now.
|
Any other return value means we called `vc-start-logentry'."
|
||||||
;; In particular this is needed for `diff-buffer-file-names' to
|
(cond*
|
||||||
;; work properly.
|
((bind* (backend (or backend
|
||||||
(default-directory (vc-call-backend backend 'root default-directory))
|
(vc-responsible-backend default-directory)))))
|
||||||
(patch (vc-call-backend backend 'prepare-patch rev))
|
((and reverse (not (eq delete 'never))
|
||||||
files whole-patch-string diff-patch-string)
|
(null (vc-find-backend-function backend
|
||||||
|
'revision-published-p))
|
||||||
|
(vc-find-backend-function backend 'delete-revision))
|
||||||
|
;; Centralized VCS implementing `delete-revision'.
|
||||||
|
(vc-call-backend backend 'delete-revision rev)
|
||||||
|
'deleted)
|
||||||
|
((and reverse interactive (not delete)
|
||||||
|
;; Distributed VCS for which we can do deletions.
|
||||||
|
(vc-find-backend-function backend 'revision-published-p)
|
||||||
|
(vc-find-backend-function backend 'delete-revision)
|
||||||
|
;; REV is safe to delete.
|
||||||
|
(not (vc-call-backend backend 'revision-published-p rev)))
|
||||||
|
;; Require confirmation, because the commit is unpublished, and so
|
||||||
|
;; this might be the only copy of the work in REV. Don't fall back
|
||||||
|
;; to making a new commit undoing REV's changes because we don't
|
||||||
|
;; know the user wants that just because they said "no" to our
|
||||||
|
;; question here, and we want to avoid two y/n prompts in a row,
|
||||||
|
;; which is probably a less good UI than this.
|
||||||
|
(cond ((or (eq interactive 'no-confirm)
|
||||||
|
(yes-or-no-p
|
||||||
|
(format "Permanently delete %s from the revision history?"
|
||||||
|
rev)))
|
||||||
|
(vc-call-backend backend 'delete-revision rev)
|
||||||
|
'deleted)
|
||||||
|
((derived-mode-p 'log-view-mode)
|
||||||
|
(user-error (substitute-command-keys "\
|
||||||
|
Use \\[log-view-revert-revisions] to create new commits \
|
||||||
|
undoing changes made by revision(s)")))
|
||||||
|
(t
|
||||||
|
(user-error (substitute-command-keys "\
|
||||||
|
Use \\[vc-revert-revision] to create a new commit undoing %s's changes")
|
||||||
|
rev))))
|
||||||
|
((and reverse delete (not (eq delete 'never))
|
||||||
|
;; Distributed VCS for which we can do deletions.
|
||||||
|
(vc-find-backend-function backend 'revision-published-p)
|
||||||
|
(vc-find-backend-function backend 'delete-revision))
|
||||||
|
;; Even though the user has explicitly requested deletion with a
|
||||||
|
;; prefix argument / invoking `vc-delete-revision' / invoking
|
||||||
|
;; `log-view-delete-revisions', by default we still confirm such a
|
||||||
|
;; destructive operation.
|
||||||
|
;; However, we want to avoid prompting twice in the case that the
|
||||||
|
;; user has set `vc-allow-rewriting-published-history' to `ask', and
|
||||||
|
;; we should avoid prompting at all in the case that
|
||||||
|
;; `vc-allow-rewriting-published-history' is another non-nil value.
|
||||||
|
;; These requirements lead to the nested `cond*' form here.
|
||||||
|
(cond*
|
||||||
|
((and vc-allow-rewriting-published-history
|
||||||
|
(not (eq vc-allow-rewriting-published-history 'ask)))
|
||||||
|
(vc-call-backend backend 'delete-revision rev)
|
||||||
|
'deleted)
|
||||||
|
((bind* (published (vc-call-backend backend 'revision-published-p rev))))
|
||||||
|
((and published
|
||||||
|
(eq vc-allow-rewriting-published-history 'ask)
|
||||||
|
(yes-or-no-p
|
||||||
|
(format "Revision %s appears published; allow rewriting history?"
|
||||||
|
rev)))
|
||||||
|
(vc-call-backend backend 'delete-revision rev)
|
||||||
|
'deleted)
|
||||||
|
(published
|
||||||
|
(user-error "Will not rewrite likely-public history"))
|
||||||
|
((yes-or-no-p
|
||||||
|
(format "Permanently delete %s from the revision history?"
|
||||||
|
rev))
|
||||||
|
(vc-call-backend backend 'delete-revision rev)
|
||||||
|
'deleted)
|
||||||
|
(t
|
||||||
|
(user-error "Aborted"))))
|
||||||
|
;; If we get this far we give up on `delete-revision', i.e. we fall
|
||||||
|
;; back to creating a commit undoing the effects of REV.
|
||||||
|
;;
|
||||||
|
;; `vc-*-prepare-patch' will always give us a patch with file names
|
||||||
|
;; relative to the VC root, so switch to there now. In particular
|
||||||
|
;; this is needed for `diff-buffer-file-names' to work properly.
|
||||||
|
((bind* (default-directory (vc-call-backend backend 'root
|
||||||
|
default-directory))
|
||||||
|
(patch (vc-call-backend backend 'prepare-patch rev))
|
||||||
|
files whole-patch-string diff-patch-string))
|
||||||
|
(t
|
||||||
(with-current-buffer (plist-get patch :buffer)
|
(with-current-buffer (plist-get patch :buffer)
|
||||||
(diff-mode)
|
(diff-mode)
|
||||||
(with-restriction
|
(with-restriction
|
||||||
|
|
@ -2218,14 +2317,14 @@ BACKEND is the VC backend to use."
|
||||||
whole-patch-string comment))
|
whole-patch-string comment))
|
||||||
nil
|
nil
|
||||||
backend
|
backend
|
||||||
diff-patch-string)))
|
diff-patch-string))))
|
||||||
|
|
||||||
;; No bindings in `vc-prefix-map' for the following two commands because
|
;; No bindings in `vc-prefix-map' for the following three items because
|
||||||
;; we expect users will usually use `log-view-revision-cherry-pick' and
|
;; we expect users will usually use `log-view-cherry-pick' and
|
||||||
;; `log-view-revision-revert', which do have bindings.
|
;; `log-view-revert-or-delete-revisions', which do have bindings.
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun vc-revision-cherry-pick (rev &optional comment initial-contents backend)
|
(defun vc-cherry-pick (rev &optional comment initial-contents backend)
|
||||||
"Copy the changes from a single revision REV to the current branch.
|
"Copy the changes from a single revision REV to the current branch.
|
||||||
When called interactively, prompts for REV.
|
When called interactively, prompts for REV.
|
||||||
Typically REV is a revision from another branch, where that branch is
|
Typically REV is a revision from another branch, where that branch is
|
||||||
|
|
@ -2256,13 +2355,55 @@ Optional argument BACKEND is the VC backend to use."
|
||||||
nil rev))
|
nil rev))
|
||||||
nil
|
nil
|
||||||
backend)))
|
backend)))
|
||||||
(vc--pick-or-revert rev nil comment initial-contents backend))
|
(vc--pick-or-revert rev nil nil nil comment initial-contents backend))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun vc-revision-revert (rev &optional comment initial-contents backend)
|
(defun vc-revert-or-delete-revision
|
||||||
|
(rev &optional interactive delete comment initial-contents backend)
|
||||||
"Undo the effects of revision REV.
|
"Undo the effects of revision REV.
|
||||||
When called interactively, prompts for REV.
|
When called interactively, prompts for REV.
|
||||||
|
|
||||||
|
When called interactively (or with optional argument INTERACTIVE
|
||||||
|
non-nil), then if the underlying VCS is distributed and REV has not been
|
||||||
|
pushed, offer to entirely delete REV.
|
||||||
|
This is instead of creating a new commit undoing the effects of REV.
|
||||||
|
|
||||||
|
With a prefix argument (or with optional argument DELETE non-nil),
|
||||||
|
only consider deleting REV, never create a new commit.
|
||||||
|
In this case INTERACTIVE is ignored.
|
||||||
|
This works only if REV has not been pushed, unless you have customized
|
||||||
|
`vc-allow-rewriting-published-history' to a non-nil value.
|
||||||
|
|
||||||
|
When called from Lisp, there are three calling conventions for the
|
||||||
|
COMMENT and INITIAL-CONTENTS optional arguments:
|
||||||
|
- COMMENT a string, INITIAL-CONTENTS nil means use that comment string
|
||||||
|
without prompting the user to edit it.
|
||||||
|
- COMMENT a string, INITIAL-CONTENTS non-nil means use that comment
|
||||||
|
string as the initial contents of the log entry buffer but stop for
|
||||||
|
editing.
|
||||||
|
- COMMENT t means use BACKEND's default revert comment for REV without
|
||||||
|
prompting for editing, and ignore INITIAL-CONTENTS.
|
||||||
|
|
||||||
|
Optional argument BACKEND is the VC backend to use.
|
||||||
|
|
||||||
|
See also `vc-revert-revision'."
|
||||||
|
(interactive (list (vc-read-revision (if current-prefix-arg
|
||||||
|
"Revision to delete: "
|
||||||
|
"Revision to revert: "))
|
||||||
|
t current-prefix-arg))
|
||||||
|
(vc--pick-or-revert rev t interactive delete
|
||||||
|
comment initial-contents backend))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun vc-revert-revision
|
||||||
|
(rev &optional comment initial-contents backend)
|
||||||
|
"Make a commit undoing the effects of revision REV.
|
||||||
|
When called interactively, prompts for REV.
|
||||||
|
|
||||||
|
This is like `vc-revert-or-delete-revision' except that it only ever makes a new
|
||||||
|
commit undoing the effects of REV, instead of considering VCS-specific
|
||||||
|
alternative mechanisms to undo the effects of REV.
|
||||||
|
|
||||||
When called from Lisp, there are three calling conventions for the
|
When called from Lisp, there are three calling conventions for the
|
||||||
COMMENT and INITIAL-CONTENTS optional arguments:
|
COMMENT and INITIAL-CONTENTS optional arguments:
|
||||||
- COMMENT a string, INITIAL-CONTENTS nil means use that comment string
|
- COMMENT a string, INITIAL-CONTENTS nil means use that comment string
|
||||||
|
|
@ -2275,7 +2416,18 @@ COMMENT and INITIAL-CONTENTS optional arguments:
|
||||||
|
|
||||||
Optional argument BACKEND is the VC backend to use."
|
Optional argument BACKEND is the VC backend to use."
|
||||||
(interactive (list (vc-read-revision "Revision to revert: ")))
|
(interactive (list (vc-read-revision "Revision to revert: ")))
|
||||||
(vc--pick-or-revert rev t comment initial-contents backend))
|
(vc--pick-or-revert rev t nil 'never comment initial-contents backend))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun vc-delete-revision (rev &optional backend)
|
||||||
|
"Delete revision REV from the revision history.
|
||||||
|
This works only if REV has not been pushed, unless you have customized
|
||||||
|
`vc-allow-rewriting-published-history' to a non-nil value.
|
||||||
|
|
||||||
|
This is the same as `vc-revert-or-delete-revision' invoked interactively
|
||||||
|
with a prefix argument."
|
||||||
|
(interactive (list (vc-read-revision "Revision to delete: ")))
|
||||||
|
(vc--pick-or-revert rev t nil t nil nil backend))
|
||||||
|
|
||||||
(declare-function diff-bounds-of-hunk "diff-mode")
|
(declare-function diff-bounds-of-hunk "diff-mode")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue