Merge devel.

This commit is contained in:
Marius Vollmer 2008-08-17 02:44:29 +03:00
commit e067f18a2e
3 changed files with 258 additions and 198 deletions

6
NEWS
View file

@ -1,4 +1,10 @@
Changes in magit 0.6: Changes in magit 0.6:
* Key bindings and command behavior for diffing, history listing, and
resetting have changed. Please see the manual.
* All buffers created by Magit are now in magit-mode and share all key
bindings.
* Bug fix: avoid looking-at-p so that magit.el works on Emacs 22 as * Bug fix: avoid looking-at-p so that magit.el works on Emacs 22 as
well. well.

328
magit.el
View file

@ -34,6 +34,8 @@
;;; TODO ;;; TODO
;; - Tags ;; - Tags
;; - Unified keymaps for status and history, etc
;; - Equivalent of interactive rebase
;; - 'Subsetting', only looking at a subset of all files. ;; - 'Subsetting', only looking at a subset of all files.
;; - Detect and handle renames and copies. ;; - Detect and handle renames and copies.
@ -117,6 +119,71 @@
(put-text-property (line-beginning-position) (line-end-position) (put-text-property (line-beginning-position) (line-end-position)
prop val)) prop val))
;;; Revisions and ranges
(defun magit-list-interesting-revisions ()
(magit-shell-lines "git branch -a | cut -c3-"))
(defun magit-read-rev (prompt &optional def)
(let* ((prompt (if def
(format "%s (default %s): " prompt def)
(format "%s: " prompt)))
(rev (completing-read prompt (magit-list-interesting-revisions)
nil nil nil nil def)))
(if (string= rev "")
nil
rev)))
(defun magit-read-rev-range (op &optional def-beg def-end)
(if current-prefix-arg
(read-string (format "%s range: " op))
(let ((beg (magit-read-rev (format "%s start" op)
def-beg)))
(if (not beg)
nil
(let ((end (magit-read-rev (format "%s end" op) def-end)))
(cons beg end))))))
(defun magit-rev-to-git (rev)
(or rev
(error "No revision specified"))
(if (string= rev ".")
(or (magit-marked-object)
(error "Commit mark not set"))
rev))
(defun magit-rev-range-to-git (range)
(or range
(error "No revision range specified"))
(if (stringp range)
range
(if (cdr range)
(format "%s..%s"
(magit-rev-to-git (car range))
(magit-rev-to-git (cdr range)))
(format "%s" (magit-rev-to-git (car range))))))
(defun magit-rev-describe (rev)
(or rev
(error "No revision specified"))
(if (string= rev ".")
"mark"
(magit-name-rev rev)))
(defun magit-rev-range-describe (range things)
(or range
(error "No revision range specified"))
(if (stringp range)
(format "%s in %s" things range)
(if (cdr range)
(format "%s from %s to %s" things
(magit-rev-describe (car range))
(magit-rev-describe (cdr range)))
(format "%s at %s" things (magit-rev-describe (car range))))))
(defun magit-default-rev ()
(magit-commit-at-point t))
;;; Sections ;;; Sections
(defun magit-insert-section (section title washer cmd &rest args) (defun magit-insert-section (section title washer cmd &rest args)
@ -237,10 +304,14 @@
(define-key map (kbd "?") 'magit-describe-thing-at-point) (define-key map (kbd "?") 'magit-describe-thing-at-point)
(define-key map (kbd ".") 'magit-mark-thing-at-point) (define-key map (kbd ".") 'magit-mark-thing-at-point)
(define-key map (kbd "=") 'magit-diff-with-mark) (define-key map (kbd "=") 'magit-diff-with-mark)
(define-key map (kbd "x") 'magit-reset-soft) (define-key map (kbd "l") 'magit-log-head)
(define-key map (kbd "X") 'magit-reset-hard) (define-key map (kbd "L") 'magit-log)
(define-key map (kbd "d") 'magit-diff-working-tree)
(define-key map (kbd "D") 'magit-diff)
(define-key map (kbd "x") 'magit-reset-head)
(define-key map (kbd "X") 'magit-reset-working-tree)
(define-key map (kbd "RET") 'magit-visit-thing-at-point) (define-key map (kbd "RET") 'magit-visit-thing-at-point)
(define-key map (kbd "b") 'magit-switch-branch) (define-key map (kbd "b") 'magit-checkout)
(define-key map (kbd "B") 'magit-create-branch) (define-key map (kbd "B") 'magit-create-branch)
(define-key map (kbd "m") 'magit-manual-merge) (define-key map (kbd "m") 'magit-manual-merge)
(define-key map (kbd "M") 'magit-automatic-merge) (define-key map (kbd "M") 'magit-automatic-merge)
@ -249,19 +320,20 @@
(define-key map (kbd "P") 'magit-push) (define-key map (kbd "P") 'magit-push)
(define-key map (kbd "c") 'magit-log-edit) (define-key map (kbd "c") 'magit-log-edit)
(define-key map (kbd "C") 'magit-add-log) (define-key map (kbd "C") 'magit-add-log)
(define-key map (kbd "l") 'magit-browse-log)
(define-key map (kbd "L") 'magit-browse-branch-log)
(define-key map (kbd "d") 'magit-diff-with-branch)
(define-key map (kbd "p") 'magit-display-process) (define-key map (kbd "p") 'magit-display-process)
map)) map))
(defvar magit-mode-hook nil) (defvar magit-mode-hook nil)
(put 'magit-mode 'mode-class 'special) (put 'magit-mode 'mode-class 'special)
(put 'magit-marked-object 'permanent-local t)
(defvar magit-marked-object nil) (defvar magit-marked-object nil)
(make-variable-buffer-local 'magit-marked-object) (make-variable-buffer-local 'magit-marked-object)
(put 'magit-marked-object 'permanent-local t)
(defvar magit-submode nil)
(make-variable-buffer-local 'magit-submode)
(put 'magit-submode 'permanent-local t)
(defun magit-mode () (defun magit-mode ()
;;; XXX - the formatting is all screwed up because of the \\[...] ;;; XXX - the formatting is all screwed up because of the \\[...]
@ -325,13 +397,13 @@ that are being merged at the top.
You can `soft reset' your repository by typing You can `soft reset' your repository by typing
`\\[magit-reset-soft]'. The current head will be set to the `\\[magit-reset-soft]'. The current head will be set to the
commit that you specify, but your working tree and the staging commit at point, but your working tree and the staging area are
area are not changed. Typing `\\[magit-reset-hard]' will do a not changed. Typing `\\[magit-reset-hard]' will do a `hard
`hard reset': all of the current head, your working tree, and the reset': all of the current head, your working tree, and the the
the index will be reverted to the commit that you specify. Doing index will be reverted to the commit at point. Doing a hard
a hard reset without actually changing the current head will thus reset without actually changing the current head will thus throw
throw away all your uncommitted changes. You can do this to away all your uncommitted changes. You can do this to abort a
abort a merge, for example. merge, for example.
When you have a remote repository configured for the current When you have a remote repository configured for the current
branch (such as when \"git clone\" has done this for you branch (such as when \"git clone\" has done this for you
@ -348,10 +420,16 @@ pushed.
(setq buffer-read-only t) (setq buffer-read-only t)
(setq major-mode 'magit-mode (setq major-mode 'magit-mode
mode-name "Magit" mode-name "Magit"
mode-line-process "") mode-line-process ""
truncate-lines t)
(use-local-map magit-mode-map) (use-local-map magit-mode-map)
(run-mode-hooks 'magit-mode-hook)) (run-mode-hooks 'magit-mode-hook))
(defun magit-mode-init (dir submode)
(setq default-directory dir
magit-submode submode)
(magit-mode))
;;; Status ;;; Status
(defun magit-wash-other-files (status) (defun magit-wash-other-files (status)
@ -470,15 +548,19 @@ pushed.
(magit-goto-section old-section)) (magit-goto-section old-section))
(magit-refresh-marks-in-buffer buf))) (magit-refresh-marks-in-buffer buf)))
(defun magit-find-status-buffer (&optional dir) (defun magit-find-buffer (submode &optional dir)
(let ((topdir (magit-get-top-dir (or dir default-directory)))) (let ((topdir (magit-get-top-dir (or dir default-directory))))
(dolist (buf (buffer-list)) (dolist (buf (buffer-list))
(if (save-excursion (if (save-excursion
(set-buffer buf) (set-buffer buf)
(and (equal default-directory topdir) (and (equal default-directory topdir)
(eq major-mode 'magit-mode))) (eq major-mode 'magit-mode)
(eq magit-submode submode)))
(return buf))))) (return buf)))))
(defun magit-find-status-buffer (&optional dir)
(magit-find-buffer 'status dir))
(defun magit-status (dir) (defun magit-status (dir)
(interactive (list (magit-read-top-dir current-prefix-arg))) (interactive (list (magit-read-top-dir current-prefix-arg)))
(save-some-buffers) (save-some-buffers)
@ -487,8 +569,7 @@ pushed.
(create-file-buffer (file-name-nondirectory (create-file-buffer (file-name-nondirectory
(directory-file-name topdir)))))) (directory-file-name topdir))))))
(switch-to-buffer buf) (switch-to-buffer buf)
(setq default-directory topdir) (magit-mode-init topdir 'status)
(magit-mode)
(magit-update-status buf))) (magit-update-status buf)))
;;; Staging ;;; Staging
@ -584,39 +665,37 @@ pushed.
;;; Branches ;;; Branches
(defun magit-list-branches () (defun magit-checkout (rev)
(magit-shell-lines "git branch -a | cut -c3-")) (interactive (list (magit-read-rev "Switch to" (magit-default-rev))))
(if rev
(defun magit-read-rev (prompt) (magit-run "git" "checkout" (magit-rev-to-git rev))))
(completing-read prompt (magit-list-branches)))
(defun magit-switch-branch (branch)
(interactive (list (magit-read-rev "Switch to branch: ")))
(if (and branch (not (string= branch "")))
(magit-run "git" "checkout" branch)))
(defun magit-read-create-branch-args () (defun magit-read-create-branch-args ()
(let* ((branches (magit-list-branches)) (let* ((cur-branch (magit-get-current-branch))
(cur-branch (magit-get-current-branch))
(branch (read-string "Create branch: ")) (branch (read-string "Create branch: "))
(parent (completing-read "Parent: " branches nil t cur-branch))) (parent (magit-read-rev "Parent" cur-branch)))
(list branch parent))) (list branch parent)))
(defun magit-create-branch (branch parent) (defun magit-create-branch (branch parent)
(interactive (magit-read-create-branch-args)) (interactive (magit-read-create-branch-args))
(if (and branch (not (string= branch "")) (if (and branch (not (string= branch ""))
parent (not (string= parent ""))) parent)
(magit-run "git" "checkout" "-b" branch parent))) (magit-run "git" "checkout" "-b"
branch
(magit-rev-to-git parent))))
;;; Merging ;;; Merging
(defun magit-manual-merge (branch) (defun magit-manual-merge (rev)
(interactive (list (magit-read-rev "Manually merge from branch: "))) (interactive (list (magit-read-rev "Manually merge")))
(magit-run "git" "merge" "--no-ff" "--no-commit" branch)) (if rev
(magit-run "git" "merge" "--no-ff" "--no-commit"
(magit-rev-to-git rev))))
(defun magit-automatic-merge (branch) (defun magit-automatic-merge (rev)
(interactive (list (magit-read-rev "Merge from branch: "))) (interactive (list (magit-read-rev "Merge")))
(magit-run "git" "merge" branch)) (if rev
(magit-run "git" "merge" (magit-rev-to-git branch))))
;;; Rebasing ;;; Rebasing
@ -636,7 +715,9 @@ pushed.
(interactive) (interactive)
(let ((info (magit-rebase-info))) (let ((info (magit-rebase-info)))
(if (not info) (if (not info)
(magit-run "git" "rebase" (magit-read-rev "Rebase against: ")) (let ((rev (magit-read-rev "Rebase to")))
(if rev
(magit-run "git" "rebase" rev)))
(let ((cursor-in-echo-area t) (let ((cursor-in-echo-area t)
(message-log-max nil)) (message-log-max nil))
(message "Rebase in progress. Abort, Skip, or Continue? ") (message "Rebase in progress. Abort, Skip, or Continue? ")
@ -651,17 +732,15 @@ pushed.
;;; Resetting ;;; Resetting
(defun magit-reset-soft (target) (defun magit-reset-head (rev)
(interactive (list (read-string "Reset history to: " "HEAD^"))) (interactive (list (magit-read-rev "Reset head to")))
(magit-run "git" "reset" "--soft" target)) (if rev
(magit-run "git" "reset" "--soft" (magit-rev-to-git rev))))
(defun magit-reset-hard (target) (defun magit-reset-working-tree ()
(interactive (list (read-string "Reset working tree (and history) to: " (interactive)
"HEAD"))) (if (yes-or-no-p "Discard all uncommitted changes? ")
(if (yes-or-no-p (magit-run "git" "reset" "--hard")))
(format "Hard reset to %s and throw away all uncommitted changes? "
target))
(magit-run "git" "reset" "--hard" target)))
;;; Push and pull ;;; Push and pull
@ -673,7 +752,7 @@ pushed.
(interactive) (interactive)
(magit-run "git" "push" "-v")) (magit-run "git" "push" "-v"))
;;; Commit ;;; Committing
(defvar magit-log-edit-map nil) (defvar magit-log-edit-map nil)
@ -748,76 +827,26 @@ pushed.
(open-line 1) (open-line 1)
(insert (format "(%s): " fun))))))))) (insert (format "(%s): " fun)))))))))
;;; History browsing ;;; Commits
(defvar magit-log-mode-map (defun magit-commit-at-point (&optional nil-ok-p)
(let ((map (make-keymap)))
(suppress-keymap map)
(define-key map (kbd "RET") 'magit-show-commit)
(define-key map (kbd ".") 'magit-mark-thing-at-point)
(define-key map (kbd "=") 'magit-diff-with-mark)
(define-key map (kbd "R") 'magit-revert-commit)
(define-key map (kbd "P") 'magit-pick-commit)
(define-key map (kbd "C") 'magit-checkout-commit)
(define-key map (kbd "l") 'magit-log-commit)
(define-key map (kbd "L") 'magit-browse-branch-log)
(define-key map (kbd "q") 'magit-quit)
map))
(defvar magit-log-mode-hook nil)
(put 'magit-log-mode 'mode-class 'special)
(defun magit-log-mode ()
"Review commit history. \\<magit-log-mode-map>
The buffer shows a summary of the (usually non-linear) history of
changes starting form a given commit. You can see the details of
a the commit on the current line by typing
`\\[magit-show-commit]'. Typing `\\[magit-log-commit] will use
the commit on the current line as the new starting point for the
summary. Typing `\\[magit-browse-branch-log]' will ask you for a
branch and show its history.
You can modify your working tree and staging area by using the
commit on the current line in a number of ways. Typing
`\\[magit-revert-commit]' will revert the change made by the
commit in your working tree (and staging area). Typing
`\\[magit-pick-commit]' will apply the commit. You can use this
to `cherry pick' changes from another branch.
Typing `\\[magit-checkout-commit]' will checkout the commit on
the current line into your working tree.
\\{magit-log-mode-map}"
(kill-all-local-variables)
(setq buffer-read-only t)
(toggle-truncate-lines t)
(setq major-mode 'magit-log-mode
mode-name "Magit Log")
(use-local-map magit-log-mode-map)
(run-mode-hooks 'magit-log-mode-hook))
(defun magit-commit-at-point ()
(let* ((info (get-text-property (point) 'magit-info)) (let* ((info (get-text-property (point) 'magit-info))
(commit (and info (commit (and info
(eq (car info) 'commit) (eq (car info) 'commit)
(cadr info)))) (cadr info))))
(or commit (if nil-ok-p
(error "No commit at point.")))) commit
(or commit
(error "No commit at point.")))))
(defun magit-revert-commit () (defun magit-revert-commit ()
(interactive) (interactive)
(magit-run "git" "revert" "--no-commit" (magit-commit-at-point))) (magit-run "git" "revert" "--no-commit" (magit-commit-at-point)))
(defun magit-pick-commit () (defun magit-apply-commit ()
(interactive) (interactive)
(magit-run "git" "cherry-pick" "--no-commit" (magit-commit-at-point))) (magit-run "git" "cherry-pick" "--no-commit" (magit-commit-at-point)))
(defun magit-checkout-commit ()
(interactive)
(magit-run "git" "checkout" (magit-commit-at-point)))
(defun magit-log-commit () (defun magit-log-commit ()
(interactive) (interactive)
(magit-browse-log (magit-commit-at-point))) (magit-browse-log (magit-commit-at-point)))
@ -855,50 +884,55 @@ the current line into your working tree.
(magit-put-line-property 'magit-info (list 'commit commit)))) (magit-put-line-property 'magit-info (list 'commit commit))))
(forward-line))) (forward-line)))
(defun magit-browse-log (head) (defun magit-log (range)
(interactive (list (magit-get-current-branch))) (interactive (list (magit-read-rev-range "Log" (magit-get-current-branch))))
(let* ((topdir (magit-get-top-dir default-directory))) (if range
(switch-to-buffer "*magit-log*") (let* ((topdir (magit-get-top-dir default-directory))
(setq default-directory topdir) (args (magit-rev-range-to-git range)))
(magit-log-mode) (switch-to-buffer "*magit-log*")
(let ((inhibit-read-only t)) (magit-mode-init topdir 'log)
(save-excursion (let ((inhibit-read-only t))
(erase-buffer) (save-excursion
(magit-insert-section 'history (format "History of %s" head) (erase-buffer)
'magit-wash-log (magit-insert-section 'history
"git" "log" "--graph" "--max-count=10000" (magit-rev-range-describe range "Commits")
"--pretty=oneline" head))) 'magit-wash-log
(magit-refresh-marks-in-buffer (current-buffer)))) "git" "log" "--graph" "--max-count=10000"
"--pretty=oneline" args)))
(magit-refresh-marks-in-buffer (current-buffer)))))
(defun magit-browse-branch-log () (defun magit-log-head ()
(interactive) (interactive)
(magit-browse-log (magit-read-rev "Browse history of branch: "))) (magit-log "HEAD"))
(defun magit-diff-with-mark ()
(interactive)
(let ((commit (magit-commit-at-point))
(marked (or (magit-marked-object)
(error "Nothing marked."))))
(magit-show-diff commit marked)))
;;; Diffing ;;; Diffing
(defun magit-show-diff (&rest args) (defun magit-diff (range)
(let ((dir default-directory) (interactive (list (magit-read-rev-range "Diff")))
(buf (get-buffer-create "*magit-diff*"))) (if range
(display-buffer buf) (let* ((dir default-directory)
(save-excursion (args (magit-rev-range-to-git range))
(set-buffer buf) (buf (get-buffer-create "*magit-diff*")))
(setq buffer-read-only t) (display-buffer buf)
(setq default-directory dir) (save-excursion
(let ((inhibit-read-only t)) (set-buffer buf)
(erase-buffer) (magit-mode-init dir 'diff)
(apply 'magit-insert-section 'diff nil 'magit-wash-diff (let ((inhibit-read-only t))
"git" "diff" args))))) (erase-buffer)
(magit-insert-section 'diff
(magit-rev-range-describe range "Changes")
'magit-wash-diff
"git" "diff" args))))))
(defun magit-diff-with-branch (branch) (defun magit-diff-working-tree (rev)
(interactive (list (magit-read-rev "Diff against: "))) (interactive (list (magit-read-rev "Diff with")))
(magit-show-diff branch)) (if rev
(magit-diff rev)))
(defun magit-diff-with-mark ()
(interactive)
(magit-diff (cons (magit-marked-object)
(magit-commit-at-point))))
;;; Markers ;;; Markers

View file

@ -57,12 +57,17 @@ put you in Magit's status buffer. You will be using it frequently, so
it is probably a good idea to bind @code{magit-status} to a key of it is probably a good idea to bind @code{magit-status} to a key of
your choice. your choice.
In addition to the status buffer, Magit will also create buffers that
show lists of commits, buffers with diffs, and other kinds of buffers.
All these buffers are in @code{magit-mode} and have the same key
bindings. Not all commands make sense in all contexts, but a given
key will always do the same thing.
@node Status @node Status
@chapter Status @chapter Status
Running @kbd{M-x magit-status} displays the main interface of Magit, Running @kbd{M-x magit-status} displays the main interface of Magit,
the status buffer. Almost all operations are initiated with single the status buffer.
letter keystrokes from that buffer.
You can have multiple status buffers active at the same time, each You can have multiple status buffers active at the same time, each
associated with its own Git repository. Running @code{magit-status} associated with its own Git repository. Running @code{magit-status}
@ -124,9 +129,9 @@ Type @kbd{c} to pop up a buffer where you can write your change
description. Once you are happy with the description, type @kbd{C-c description. Once you are happy with the description, type @kbd{C-c
C-c} in that buffer to commit the staged changes. C-c} in that buffer to commit the staged changes.
Typing @kbd{C} will also pop up the change description buffer, but it Typing @kbd{C} will also pop up the change description buffer, but in
will also try to insert a ChangeLog-style entry for the change that addition, it will try to insert a ChangeLog-style entry for the change
point is in. that point is in.
If the current branch is associated with a remote repository, the If the current branch is associated with a remote repository, the
status buffer will show a fourth section, named @emph{Unpushed status buffer will show a fourth section, named @emph{Unpushed
@ -137,37 +142,46 @@ Pulling} for more information.
@node History @node History
@chapter History @chapter History
To browse the repository history, type @kbd{l} or @kbd{L} in the To show the repository history of your current head, type @kbd{l}. A
status buffer. Typing @kbd{l} will show the history starting from the new buffer will be shown that displays the history in a terse form.
current head, while @kbd{L} will ask for a starting point.
A new buffer will be shown that displays the history in a terse form.
The first paragraph of each commit message is displayed, next to a The first paragraph of each commit message is displayed, next to a
representation of the relationships between commits. representation of the relationships between commits.
Typing @kbd{L} will ask for the starting and end point of the history.
This can be used to show the commits that are in one branch, but not
in another, for example.
You can move point to a commit and then cause various things to happen You can move point to a commit and then cause various things to happen
with it. with it. (The following commands work in any list of commit, such as
the one shown in the @emph{Unpushed commits} section.)
Typing @kbd{RET} will pop up more information about the current Typing @kbd{RET} will pop up more information about the current
commit and typing @kbd{l} will use it as the new starting point of the commit.
history buffer.
Typing @kbd{R} will revert the current commit in your working tree and Typing @kbd{a} will apply the current commit to your working tree and
staging area. Thus, it will apply the changes made by that commit in staging area. This is useful when you are browsing the history of
reverse. This is obviously useful to cleanly undo changes that turned some other branch and you want to `cherry-pick' some changes from it
out to be wrong. for your current branch. A typical situation is applying selected bug
fixes from the development version of a program to a release branch.
Typing @kbd{P} will apply the current commit in the normal way. This Typing @kbd{v} will revert the current commit. Thus, it will apply
is useful when you are browsing the history of some other branch and the changes made by that commit in reverse. This is obviously useful
you want to `cherry-pick' some changes from it for your current to cleanly undo changes that turned out to be wrong.
branch. A typical situation is applying selected bug fixes from the
development version of a program to a release branch.
Typing @kbd{C} will switch your working tree to the current commit. Typing @kbd{=} will show the differences from the current commit to
the @dfn{marked} commit.
You can also mark the current commit by typing @kbd{.}. Once you have You can mark the current commit by typing @kbd{.}. Some commands,
marked a commit, you can show the differences between it and the such as @kbd{=}, will use the current commit and the marked commit as
current commit by typing @kbd{=}. implicit arguments. Other commands will offer the marked commit as a
default when prompting for their arguments.
@node Diffing
@chapter Diffing
To show the changes from you working tree to another revision, type
@kbd{d}. To show the changes between two arbitrary revisions, type
@kbd{D}.
@node Resetting @node Resetting
@chapter Resetting @chapter Resetting
@ -176,37 +190,43 @@ Once you have added a commit to your local repository, you can not
change that commit anymore in any way. But you can reset your current change that commit anymore in any way. But you can reset your current
head to an earlier commit and start over. head to an earlier commit and start over.
If you have published your history already, rewriting history in this If you have published your history already, rewriting it in this way
way can be confusing and should be avoided. However, rewriting your can be confusing and should be avoided. However, rewriting your local
local history is fine and it is often cleaner to fix mistakes this way history is fine and it is often cleaner to fix mistakes this way than
than by reverting commits (with @kbd{R} in the history buffer, for by reverting commits (with @kbd{R}, for example).
example).
Magit gives you two ways to reset your current head: soft and hard. Typing @kbd{x} will ask for a revision and reset your current head to
Type @kbd{x} to do a soft reset. This will change the current head to it. No changes will be made to your working tree and staging area.
the commit that you specify, but your current working tree and staging Thus, the @emph{Staged changes} section in the status buffer will show
area will not be touched. This is useful to redoing the last commit the changes that you have removed from your commit history. You can
to correct the commit message, for example. commit the changes again as if you had just made them, thus rewriting
history.
Type @kbd{X} to do a hard reset. This will reset the current head to Typing @kbd{x} while point is in a line that describes a commit will
the commit you specify and will check it out so that your working tree offer this commit as the default revision to reset to. Thus, you can
and staging area will match it. In other words, a hard reset will move point to one of the commits in the @emph{Unpushed commits}
throw away the history completely, which can be useful to abort section and hit @kbd{x RET} to reset your current head to it.
experimental changes (like merging a branch just to see what happens).
In particular, doing a hard reset to HEAD will have no effect on the Type @kbd{X} to reset your working tree and staging area to the most
current head, but it will reset your working tree and staging area recently committed state. This will discard your local modifications,
back to the last committed state. so be careful.
@node Branching and Merging @node Branching and Merging
@chapter Branching and Merging @chapter Branching and Merging
The current branch is indicated in the header of the status buffer. The current branch is indicated in the header of the status buffer.
You can check out a different branch by typing @kbd{b}. To create a You can switch to a different branch by typing @kbd{b}. This will
new branch and check it out immediately, type @kbd{B}. immediately checkout the branch into your working copy, so you
shouldn't have any local modifications when switching branches.
You can also compare your working tree with some other branch. Type Similar to @kbs{x}, typing @kbd{b} while point is at a commit
@kbd{d} and then specify the branch to compare with. description will offer that commit as the default to switch to.
This will result in a detached head.
To create a new branch and switch to it immediately, type @kbd{B}.
@node Merging
@chapter Merging
Magit offers two ways to merge branches: manually and automatic. A Magit offers two ways to merge branches: manually and automatic. A
manual merge will apply all changes to your working tree and staging manual merge will apply all changes to your working tree and staging
@ -217,9 +237,9 @@ Type @kbd{m} to initiate a manual merge, and type @kbd{M} for a
automatic merge. automatic merge.
A manual merge is useful when carefully merging a new feature that you A manual merge is useful when carefully merging a new feature that you
want to review and test before committing it. A automatic merge is want to review and test before even committing it. A automatic merge
appropriate when you are on a feature branch and want to catch up with is appropriate when you are on a feature branch and want to catch up
the master, say. with the master, say.
After initiating a manual merge, the header of the status buffer will After initiating a manual merge, the header of the status buffer will
remind you that the next commit will be a merge commit (with more than remind you that the next commit will be a merge commit (with more than