Commit 938c052e authored by Jonas Bernoulli's avatar Jonas Bernoulli

magit-unstage: reverse committed changes

Add new command `magit-reverse-in-index' but do not bind any key to it.
Instead make `magit-unstage' call it when the user attempts to unstage
a committed change.  Setting the new option `magit-unstage-committed'
to `nil' disables this behavior.
parent 534207fd
......@@ -19,6 +19,15 @@ Updates since v2.4.1
Users who use Tramp and experience delays, should consider setting
the option to `magit-auto-revert-repository-buffer-p'.
* By default, invoking `magit-unstage' on a committed change how
performs an action which is somewhat similar to unstaging. The
change is reverted in the index, but not the working tree. This
allows extracting changes from HEAD.
Setting the new option `magit-unstage-committed' to nil, disables
this behavior. Attempting to unstage a committed change would then
result in an error again.
* The heading of the section which lists commits that exist in the
current branch but not in its upstream was changed from "Unpushed
to <upstream>" to "Unmerged into <upstream>", because one usually
......
......@@ -2579,6 +2579,8 @@ Besides staging and unstaging, Magit also provides several other
once, a hunk, multiple hunks at once, and on parts of a hunk. These
apply variants are described in the next section.
You can also use Ediff to stage and unstage. See [[*Ediffing]].
- Key: s, magit-stage
Add the change at point to the staging area.
......@@ -2594,21 +2596,48 @@ apply variants are described in the next section.
Remove the change at point from the staging area.
Only staged changes can be unstaged. But by default this command
performs an action that is somewhat similar to unstaging, when it is
called on a committed change: it reverses the change in the index
but not in the working tree.
- Key: U, magit-unstage-all
Remove all changes from the staging area.
- User Option: magit-unstage-committed
This option controls whether ~magit-unstage~ "unstages" committed
changes by reversing them in the index but not the working tree.
The alternative is to raise an error.
- Key: M-x magit-reverse-in-index, magit-reverse-in-index
This command reverses the committed change at point in the index but
not the working tree. By default no key is bound directly to this
command, but it is indirectly called when ~u~ (~magit-unstage~) is
pressed on a committed change.
This allows extracting a change from ~HEAD~, while leaving it in the
working tree, so that it can later be committed using a separate
commit. A typical workflow would be:
0. Optionally make sure that there are no uncommitted changes.
1. Visit the ~HEAD~ commit and navigate to the change that should
not have been included in that commit.
2. Type ~u~ (~magit-unstage~) to reverse it in the index.
This assumes that ~magit-unstage-committed-changes~ is non-nil.
3. Type ~c e~ to extend ~HEAD~ with the staged changes,
including those that were already staged before.
4. Optionally stage the remaining changes using ~s~ or ~S~ and then
type ~c c~ to create a new commit.
- Key: M-x magit-reset-index, magit-reset-index
Reset the index to some commit. The commit is read from the user
and defaults to the commit at point. If there is no commit at
point, then it defaults to ~HEAD~.
To stage a smaller unit than a range of lines, similar to ~git add
--patch~ followed by ~e~ would do, then you can use ~magit-ediff-stage~ to
do so.
*** Staging from file-visiting buffers
Fine-grained un-/staging has to be done from the status or a diff
......
......@@ -3533,6 +3533,8 @@ Besides staging and unstaging, Magit also provides several other
once, a hunk, multiple hunks at once, and on parts of a hunk. These
apply variants are described in the next section.
You can also use Ediff to stage and unstage. See @ref{Ediffing,Ediffing}.
@table @asis
@kindex s
@cindex magit-stage
......@@ -3555,12 +3557,61 @@ argument also stage previously untracked (but not ignored) files.
Remove the change at point from the staging area.
Only staged changes can be unstaged. But by default this command
performs an action that is somewhat similar to unstaging, when it is
called on a committed change: it reverses the change in the index
but not in the working tree.
@kindex U
@cindex magit-unstage-all
@item @kbd{U} @tie{}@tie{}@tie{}@tie{}(@code{magit-unstage-all})
Remove all changes from the staging area.
@end table
@defopt magit-unstage-committed
This option controls whether @code{magit-unstage} "unstages" committed
changes by reversing them in the index but not the working tree.
The alternative is to raise an error.
@end defopt
@table @asis
@kindex M-x magit-reverse-in-index
@cindex magit-reverse-in-index
@item @kbd{M-x magit-reverse-in-index} @tie{}@tie{}@tie{}@tie{}(@code{magit-reverse-in-index})
This command reverses the committed change at point in the index but
not the working tree. By default no key is bound directly to this
command, but it is indirectly called when @code{u} (@code{magit-unstage}) is
pressed on a committed change.
This allows extracting a change from @code{HEAD}, while leaving it in the
working tree, so that it can later be committed using a separate
commit. A typical workflow would be:
@itemize
@item
Optionally make sure that there are no uncommitted changes.
@item
Visit the @code{HEAD} commit and navigate to the change that should
not have been included in that commit.
@item
Type @code{u} (@code{magit-unstage}) to reverse it in the index.
This assumes that @code{magit-unstage-committed-changes} is non-nil.
@item
Type @code{c e} to extend @code{HEAD} with the staged changes,
including those that were already staged before.
@item
Optionally stage the remaining changes using @code{s} or @code{S} and then
type @code{c c} to create a new commit.
@end itemize
@kindex M-x magit-reset-index
@cindex magit-reset-index
@item @kbd{M-x magit-reset-index} @tie{}@tie{}@tie{}@tie{}(@code{magit-reset-index})
......@@ -3570,11 +3621,6 @@ and defaults to the commit at point. If there is no commit at
point, then it defaults to @code{HEAD}.
@end table
To stage a smaller unit than a range of lines, similar to @code{git add
--patch} followed by @code{e} would do, then you can use @code{magit-ediff-stage} to
do so.
@menu
* Staging from file-visiting buffers::
@end menu
......
......@@ -52,6 +52,22 @@
:group 'magit
:type 'boolean)
(defcustom magit-unstage-committed t
"Whether unstaging a committed change reverts it instead.
A committed change cannot be unstaged, because staging and
unstaging are actions that are concern with the differences
between the index and the working tree, not with committed
changes.
If this option is non-nil (the default), then typing \"u\"
(`magit-unstage') on a committed change, causes it to be
reversed in the index but not the working tree. For more
information see command `magit-reverse-in-index'."
:package-version '(magit . "2.4.1")
:group 'magit-commands
:type 'boolean)
;;; Commands
;;;; Apply
......@@ -256,8 +272,8 @@ ignored) files.
(`(staged file) (magit-unstage-1 (list (magit-section-value it))))
(`(staged files) (magit-unstage-1 (magit-region-values)))
(`(staged list) (magit-unstage-all))
(`(committed ,_) (if (bound-and-true-p magit-unstage-use-anti-stage)
(magit-anti-stage)
(`(committed ,_) (if magit-unstage-committed
(magit-reverse-in-index)
(user-error "Cannot unstage committed changes")))
(`(undefined ,_) (user-error "Cannot unstage this change")))))
......@@ -516,6 +532,25 @@ without requiring confirmation."
(when binaries
(user-error "Cannot reverse binary files"))))
(defun magit-reverse-in-index (&rest args)
"Reverse the change at point in the index but not the working tree.
Use this command to extract a change from `HEAD', while leaving
it in the working tree, so that it can later be committed using
a separate commit. A typical workflow would be:
0. Optionally make sure that there are no uncommitted changes.
1. Visit the `HEAD' commit and navigate to the change that should
not have been included in that commit.
2. Type \"u\" (`magit-unstage') to reverse it in the index.
This assumes that `magit-unstage-committed-changes' is non-nil.
3. Type \"c e\" to extend `HEAD' with the staged changes,
including those that were already staged before.
4. Optionally stage the remaining changes using \"s\" or \"S\"
and then type \"c c\" to create a new commit."
(interactive)
(magit-reverse (cons "--cached" args)))
;;; magit-apply.el ends soon
(provide 'magit-apply)
;; Local Variables:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment