mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
New commands to rewind decentralized VCS branches
* lisp/vc/vc.el (vc--remove-revisions-from-end): New function. (vc-uncommit-revisions-from-end, vc-delete-revisions-from-end): * lisp/vc/log-view.el (log-view-uncommit-revisions-from-end) (log-view-delete-revisions-from-end): New commands (bug#79408). (log-view-mode-map): Bind them. * doc/emacs/maintaining.texi (VC Change Log): * doc/emacs/vc1-xtra.texi (VC Auto-Reverting): * etc/NEWS: Document them.
This commit is contained in:
parent
dcc909917b
commit
11b68c6223
7 changed files with 194 additions and 2 deletions
|
|
@ -877,6 +877,7 @@ Miscellaneous Commands and Features of VC
|
||||||
* Editing VC Commands:: Editing the VC shell commands that Emacs will run.
|
* Editing VC Commands:: Editing the VC shell commands that Emacs will run.
|
||||||
* Preparing Patches:: Preparing and composing patches from within VC.
|
* Preparing Patches:: Preparing and composing patches from within VC.
|
||||||
* VC Auto-Reverting:: Updating buffer contents after VCS operations.
|
* VC Auto-Reverting:: Updating buffer contents after VCS operations.
|
||||||
|
* Rewinding Branches:: Commands to delete revisions from ends of branches.
|
||||||
|
|
||||||
Customizing VC
|
Customizing VC
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1273,6 +1273,15 @@ the revision at point, or the changes from all marked revisions
|
||||||
@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-revert-or-delete-revisions}).
|
marked revisions (@code{log-view-revert-or-delete-revisions}).
|
||||||
|
|
||||||
|
@item x
|
||||||
|
Delete revisions newer than the revision at point from the current
|
||||||
|
branch without touching the working tree
|
||||||
|
(@code{log-view-uncommit-revisions-from-end}).
|
||||||
|
|
||||||
|
@item X
|
||||||
|
Delete revisions newer than the revision at point from the current
|
||||||
|
branch (@code{log-view-delete-revisions-from-end}).
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@vindex vc-log-show-limit
|
@vindex vc-log-show-limit
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
* Editing VC Commands:: Editing the VC shell commands that Emacs will run.
|
* Editing VC Commands:: Editing the VC shell commands that Emacs will run.
|
||||||
* Preparing Patches:: Preparing and composing patches from within VC.
|
* Preparing Patches:: Preparing and composing patches from within VC.
|
||||||
* VC Auto-Reverting:: Updating buffer contents after VCS operations.
|
* VC Auto-Reverting:: Updating buffer contents after VCS operations.
|
||||||
|
* Rewinding Branches:: Commands to delete revisions from ends of branches.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Change Logs and VC
|
@node Change Logs and VC
|
||||||
|
|
@ -678,6 +679,60 @@ contents, regardless of whether Emacs initiated those operations.
|
||||||
@xref{VC Mode Line}, for details regarding Auto Revert mode in buffers
|
@xref{VC Mode Line}, for details regarding Auto Revert mode in buffers
|
||||||
visiting tracked files (which is what @code{vc-auto-revert-mode} enables).
|
visiting tracked files (which is what @code{vc-auto-revert-mode} enables).
|
||||||
|
|
||||||
|
@node Rewinding Branches
|
||||||
|
@subsubsection Rewinding Branches
|
||||||
|
@cindex rewinding a branch (VC)
|
||||||
|
|
||||||
|
@table @kbd
|
||||||
|
@item M-x vc-delete-revisions-from-end
|
||||||
|
Delete revisions from the end of the current branch.
|
||||||
|
|
||||||
|
@item M-x vc-uncommit-revisions-from-end
|
||||||
|
Delete revisions from the end of the current branch without touching the
|
||||||
|
working tree.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@findex vc-delete-revisions-from-end
|
||||||
|
For decentralized version control systems (@pxref{VCS Repositories}),
|
||||||
|
these commands provide ways to move the current branch back to an
|
||||||
|
earlier revision. @code{vc-delete-revisions-from-end} prompts for a
|
||||||
|
revision, then removes all revisions from the end of the branch up to
|
||||||
|
but not including the specified revision. We say that the branch is
|
||||||
|
@dfn{rewound} back to the specified revision.
|
||||||
|
|
||||||
|
This command removes the changes made by the revisions from the
|
||||||
|
working tree. Therefore, if there are any uncommitted changes, they
|
||||||
|
must be reverted, first (@pxref{VC Undo}). This command will prompt you
|
||||||
|
to do that if necessary. If you supply a prefix argument, Emacs will
|
||||||
|
delete uncommitted changes without prompting.
|
||||||
|
|
||||||
|
@cindex uncommitting revisions
|
||||||
|
@findex vc-uncommit-revisions-from-end
|
||||||
|
To ``uncommit'' a revision means to remove it from the revision
|
||||||
|
history without removing its changes from the working tree. It is as
|
||||||
|
though you had made the changes but had not yet checked them in. The
|
||||||
|
command @code{vc-uncommit-revisions-from-end} prompts for a revision,
|
||||||
|
and then uncommits all revisions from the end of the branch up to but
|
||||||
|
not including the specified revision. The branch is rewound back to the
|
||||||
|
specified revision but the changes are left behind in the working tree.
|
||||||
|
|
||||||
|
When rewinding the current branch, if all the revisions deleted from
|
||||||
|
the revision history are among those you have pulled or pushed, then
|
||||||
|
these operations do not permanently delete anything: a simple
|
||||||
|
@w{@kbd{C-x v +}} (@pxref{Pulling / Pushing}) will bring the revisions
|
||||||
|
back. On the other hand, if there are new revisions on the end of the
|
||||||
|
branch that have not yet been pushed, then these commands will delete
|
||||||
|
them permanently. Emacs tries to detect this situation and ask you if
|
||||||
|
you are sure you want to delete them.
|
||||||
|
|
||||||
|
Alternative ways to access this functionality are the
|
||||||
|
@code{log-view-uncommit-revisions-from-end} and
|
||||||
|
@code{log-view-delete-revisions-from-end} commands, bound to @kbd{x} and
|
||||||
|
@kbd{X}, respectively, in Log View mode buffers (@pxref{VC Change Log}).
|
||||||
|
Compared to using the commands described here directly, the Log View
|
||||||
|
mode commands can make it easier to be sure you are rewinding back to
|
||||||
|
the revision you intend.
|
||||||
|
|
||||||
@node Customizing VC
|
@node Customizing VC
|
||||||
@subsection Customizing VC
|
@subsection Customizing VC
|
||||||
|
|
||||||
|
|
|
||||||
7
etc/NEWS
7
etc/NEWS
|
|
@ -2393,6 +2393,13 @@ From Log View buffers, you can use 'C' to cherry-pick the revision at
|
||||||
point or all marked revisions, and 'R' to undo the revision at point or
|
point or all marked revisions, and 'R' to undo the revision at point or
|
||||||
all marked revisions.
|
all marked revisions.
|
||||||
|
|
||||||
|
+++
|
||||||
|
*** New commands to rewind branches.
|
||||||
|
In Log View mode, 'x' deletes revisions newer than the revision at point
|
||||||
|
from the history of the current branch, though without undoing the
|
||||||
|
changes made by those revisions to the working tree. 'X' is similar
|
||||||
|
except that it does remove the changes from the working tree.
|
||||||
|
|
||||||
*** 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.
|
||||||
It is intended to be added to the 'log-edit-done-hook' so that
|
It is intended to be added to the 'log-edit-done-hook' so that
|
||||||
|
|
|
||||||
|
|
@ -2235,7 +2235,8 @@ With a prefix argument, try to REVERSE the hunk."
|
||||||
|
|
||||||
This command is useful in buffers generated by \\[vc-diff] and \\[vc-root-diff],
|
This command is useful in buffers generated by \\[vc-diff] and \\[vc-root-diff],
|
||||||
especially when preparing to commit the patch with \\[vc-next-action].
|
especially when preparing to commit the patch with \\[vc-next-action].
|
||||||
You can use \\<diff-mode-map>\\[diff-hunk-kill] to temporarily remove changes that you intend to
|
You can use \\<diff-mode-map>\\[diff-hunk-kill] \
|
||||||
|
to temporarily remove changes that you intend to
|
||||||
include in a separate commit or commits, and you can use this command
|
include in a separate commit or commits, and you can use this command
|
||||||
to permanently drop changes you didn't intend, or no longer want.
|
to permanently drop changes you didn't intend, or no longer want.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@
|
||||||
(autoload 'vc-find-revision "vc")
|
(autoload 'vc-find-revision "vc")
|
||||||
(autoload 'vc-diff-internal "vc")
|
(autoload 'vc-diff-internal "vc")
|
||||||
(autoload 'vc--pick-or-revert "vc")
|
(autoload 'vc--pick-or-revert "vc")
|
||||||
|
(autoload 'vc--remove-revisions-from-end "vc")
|
||||||
(autoload 'vc--prompt-other-working-tree "vc")
|
(autoload 'vc--prompt-other-working-tree "vc")
|
||||||
|
|
||||||
(defvar cvs-minor-wrap-function)
|
(defvar cvs-minor-wrap-function)
|
||||||
|
|
@ -142,7 +143,9 @@
|
||||||
"TAB" #'log-view-msg-next
|
"TAB" #'log-view-msg-next
|
||||||
"<backtab>" #'log-view-msg-prev
|
"<backtab>" #'log-view-msg-prev
|
||||||
"C" #'log-view-cherry-pick
|
"C" #'log-view-cherry-pick
|
||||||
"R" #'log-view-revert-or-delete-revisions)
|
"R" #'log-view-revert-or-delete-revisions
|
||||||
|
"x" #'log-view-uncommit-revisions-from-end
|
||||||
|
"X" #'log-view-delete-revisions-from-end)
|
||||||
|
|
||||||
(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."
|
||||||
|
|
@ -828,6 +831,36 @@ See also `vc-revert-or-delete-revision'."
|
||||||
t current-prefix-arg))
|
t current-prefix-arg))
|
||||||
(log-view--pick-or-revert directory nil t interactive delete))
|
(log-view--pick-or-revert directory nil t interactive delete))
|
||||||
|
|
||||||
|
(defun log-view-uncommit-revisions-from-end ()
|
||||||
|
"Uncommit revisions newer than the revision at point.
|
||||||
|
The revision at point must be on the current branch. The newer
|
||||||
|
revisions are deleted from the revision history but the changes made by
|
||||||
|
those revisions to files in the working tree are not undone.
|
||||||
|
|
||||||
|
To delete revisions from the revision history and also undo the changes
|
||||||
|
in the working tree, see `log-edit-delete-revisions-from-end'."
|
||||||
|
(interactive)
|
||||||
|
(vc--remove-revisions-from-end (log-view-current-tag)
|
||||||
|
nil t log-view-vc-backend)
|
||||||
|
(revert-buffer))
|
||||||
|
|
||||||
|
(defun log-view-delete-revisions-from-end (&optional discard)
|
||||||
|
"Delete revisions newer than the revision at point.
|
||||||
|
The revision at point must be on the current branch. The newer
|
||||||
|
revisions are deleted from the revision history and the changes made by
|
||||||
|
those revisions to files in the working tree are undone.
|
||||||
|
If the are uncommitted changes, prompts to discard them.
|
||||||
|
With a prefix argument (when called from Lisp, with optional argument
|
||||||
|
DISCARD non-nil), discard any uncommitted changes without prompting.
|
||||||
|
|
||||||
|
To delete revisions from the revision history without undoing the
|
||||||
|
changes in the working tree, see `log-edit-uncommit-revisions-from-end'."
|
||||||
|
(interactive "P")
|
||||||
|
(vc--remove-revisions-from-end (log-view-current-tag)
|
||||||
|
(if discard 'discard t)
|
||||||
|
t log-view-vc-backend)
|
||||||
|
(revert-buffer))
|
||||||
|
|
||||||
;; These are left unbound by default. A user who doesn't like the DWIM
|
;; 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
|
;; behavior of `log-view-revert-or-delete-revisions' can unbind that and
|
||||||
;; bind these two commands instead.
|
;; bind these two commands instead.
|
||||||
|
|
|
||||||
|
|
@ -2429,6 +2429,92 @@ with a prefix argument."
|
||||||
(interactive (list (vc-read-revision "Revision to delete: ")))
|
(interactive (list (vc-read-revision "Revision to delete: ")))
|
||||||
(vc--pick-or-revert rev t nil t nil nil backend))
|
(vc--pick-or-revert rev t nil t nil nil backend))
|
||||||
|
|
||||||
|
(defun vc--remove-revisions-from-end (rev delete prompt backend)
|
||||||
|
"Delete revisions newer than REV.
|
||||||
|
DELETE non-nil means to remove the changes from the working tree.
|
||||||
|
DELETE `discard' means to silently discard uncommitted changes.
|
||||||
|
PROMPT non-nil means to always get confirmation. (This is passed by
|
||||||
|
`log-view-uncommit-revisions-from-end' and `log-view-delete-revisions'
|
||||||
|
because they have single-letter bindings and don't otherwise prompt, so
|
||||||
|
might be easy to use accidentally.)
|
||||||
|
BACKEND is the VC backend."
|
||||||
|
(let ((backend (or backend (vc-responsible-backend default-directory))))
|
||||||
|
(unless (eq (vc-call-backend backend 'revision-granularity)
|
||||||
|
'repository)
|
||||||
|
(error "Requires VCS with whole-repository revision granularity"))
|
||||||
|
(unless (vc-find-backend-function backend 'revision-published-p)
|
||||||
|
(signal 'vc-not-supported (list 'revision-published-p backend)))
|
||||||
|
;; Rewinding the end of the branch to REV does not in itself mean
|
||||||
|
;; rewriting public history because a subsequent pull will generally
|
||||||
|
;; undo the rewinding. Rewinding and then making new commits before
|
||||||
|
;; syncing with the upstream will necessitate merging, but that's
|
||||||
|
;; just part of the normal workflow with a distributed VCS.
|
||||||
|
;; Therefore we don't prompt about deleting published revisions (and
|
||||||
|
;; so we ignore `vc-allow-rewriting-published-history').
|
||||||
|
;; We do care about deleting *unpublished* revisions, however,
|
||||||
|
;; because that could potentially mean losing work permanently.
|
||||||
|
(when (if (vc-call-backend backend 'revision-published-p
|
||||||
|
(vc-call-backend backend
|
||||||
|
'working-revision-symbol))
|
||||||
|
(and prompt
|
||||||
|
(not (y-or-n-p
|
||||||
|
(format "Uncommit revisions newer than %s?"
|
||||||
|
rev))))
|
||||||
|
;; FIXME: Actually potentially not all revisions newer than
|
||||||
|
;; REV would be permanently deleted -- only those which are
|
||||||
|
;; unpushed. So this prompt is a little misleading.
|
||||||
|
(not (yes-or-no-p
|
||||||
|
(format "Permanently delete revisions newer than %s?"
|
||||||
|
rev))))
|
||||||
|
(user-error "Aborted"))
|
||||||
|
(if delete
|
||||||
|
;; FIXME: As discussed in bug#79408, instead of just failing if
|
||||||
|
;; the user declines reverting the changes, we would leave
|
||||||
|
;; behind some sort of conflict for the user to resolve, like we
|
||||||
|
;; do when there is a merge conflict.
|
||||||
|
(let ((root (vc-root-dir)))
|
||||||
|
(when (vc-dir-status-files root nil backend)
|
||||||
|
(if (eq delete 'discard)
|
||||||
|
(vc-revert-file root)
|
||||||
|
(let ((vc-buffer-overriding-fileset `(,backend (,root))))
|
||||||
|
(vc-revert))))
|
||||||
|
(vc-call-backend backend 'delete-revisions-from-end rev))
|
||||||
|
(vc-call-backend backend 'uncommit-revisions-from-end rev))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun vc-uncommit-revisions-from-end (rev &optional backend)
|
||||||
|
"Delete revisions newer than REV without touching the working tree.
|
||||||
|
REV must be on the current branch. The newer revisions are deleted from
|
||||||
|
the revision history but the changes made by those revisions to files in
|
||||||
|
the working tree are not undone.
|
||||||
|
When called interactively, prompts for REV.
|
||||||
|
BACKEND is the VC backend.
|
||||||
|
|
||||||
|
To delete revisions from the revision history and also undo the changes
|
||||||
|
in the working tree, see `vc-delete-revisions-from-end'."
|
||||||
|
(interactive (list
|
||||||
|
(vc-read-revision "Uncommit revisions newer than revision: ")))
|
||||||
|
(vc--remove-revisions-from-end rev nil nil backend))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun vc-delete-revisions-from-end (rev &optional discard backend)
|
||||||
|
"Delete revisions newer than REV.
|
||||||
|
REV must be on the current branch. The newer revisions are deleted from
|
||||||
|
the revision history and the changes made by those revisions to files in
|
||||||
|
the working tree are undone.
|
||||||
|
When called interactively, prompts for REV.
|
||||||
|
If the are uncommitted changes, prompts to discard them.
|
||||||
|
With a prefix argument (when called from Lisp, with optional argument
|
||||||
|
DISCARD non-nil), discard any uncommitted changes without prompting.
|
||||||
|
BACKEND is the VC backend.
|
||||||
|
|
||||||
|
To delete revisions from the revision history without undoing the
|
||||||
|
changes in the working tree, see `vc-uncommit-revisions-from-end'."
|
||||||
|
(interactive (list
|
||||||
|
(vc-read-revision "Delete revisions newer than revision: ")
|
||||||
|
current-prefix-arg))
|
||||||
|
(vc--remove-revisions-from-end rev (if discard 'discard t) nil backend))
|
||||||
|
|
||||||
(declare-function diff-bounds-of-hunk "diff-mode")
|
(declare-function diff-bounds-of-hunk "diff-mode")
|
||||||
|
|
||||||
(defun vc-default-checkin-patch (_backend patch-string comment)
|
(defun vc-default-checkin-patch (_backend patch-string comment)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue