From d8184590caef8fabba3870a488a9a5b34b352267 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Fri, 15 Aug 2008 21:36:18 +0300 Subject: [PATCH 01/14] Updated TODO --- magit.el | 1 + 1 file changed, 1 insertion(+) diff --git a/magit.el b/magit.el index 322cc348..537ca867 100644 --- a/magit.el +++ b/magit.el @@ -34,6 +34,7 @@ ;;; TODO ;; - Tags +;; - Equivalent of interactive rebase ;; - 'Subsetting', only looking at a subset of all files. ;; - Detect and handle renames and copies. From 48386c915c652eb5aed0da0d42e46b9fa3f2b7f5 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sat, 16 Aug 2008 16:15:14 +0300 Subject: [PATCH 02/14] Unified keymaps, make resetting use the commit at point instead of asking, changed Unpushed commits to Recent commits. --- magit.el | 52 +++++++++++++++++++++++++++++----------------------- magit.texi | 12 +++++++----- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/magit.el b/magit.el index 537ca867..2271fded 100644 --- a/magit.el +++ b/magit.el @@ -34,6 +34,7 @@ ;;; TODO ;; - Tags +;; - Unified keymaps for status and history, etc ;; - Equivalent of interactive rebase ;; - 'Subsetting', only looking at a subset of all files. ;; - Detect and handle renames and copies. @@ -235,9 +236,13 @@ (define-key map (kbd "S") 'magit-stage-all) (define-key map (kbd "u") 'magit-unstage-thing-at-point) (define-key map (kbd "i") 'magit-ignore-thing-at-point) - (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-diff-with-mark) + (define-key map (kbd "?") 'magit-log-commit) + (define-key map (kbd "a") 'magit-apply-commit) + (define-key map (kbd "v") 'magit-revert-commit) + (define-key map (kbd "H") 'magit-checkout-commit) (define-key map (kbd "x") 'magit-reset-soft) (define-key map (kbd "X") 'magit-reset-hard) (define-key map (kbd "RET") 'magit-visit-thing-at-point) @@ -254,6 +259,7 @@ (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 "q") 'magit-quit) map)) (defvar magit-mode-hook nil) @@ -326,13 +332,13 @@ that are being merged at the top. You can `soft reset' your repository by typing `\\[magit-reset-soft]'. The current head will be set to the -commit that you specify, but your working tree and the staging -area are not changed. Typing `\\[magit-reset-hard]' will do a -`hard reset': all of the current head, your working tree, and the -the index will be reverted to the commit that you specify. Doing -a hard reset without actually changing the current head will thus -throw away all your uncommitted changes. You can do this to -abort a merge, for example. +commit at point, but your working tree and the staging area are +not changed. Typing `\\[magit-reset-hard]' will do a `hard +reset': all of the current head, your working tree, and the the +index will be reverted to the commit at point. Doing a hard +reset without actually changing the current head will thus throw +away all your uncommitted changes. You can do this to abort a +merge, for example. When you have a remote repository configured for the current branch (such as when \"git clone\" has done this for you @@ -462,11 +468,10 @@ pushed. (magit-insert-section 'staged "Staged changes:" 'magit-wash-diff "git" "diff" "--cached") - (if remote - (magit-insert-section 'unpushed - "Unpushed commits:" 'magit-wash-log - "git" "log" "--graph" "--pretty=oneline" - (format "%s/%s..HEAD" remote branch)))) + (magit-insert-section 'unpushed + "Recent commits:" 'magit-wash-log + "git" "log" "--graph" "--max-count=10" + "--pretty=oneline")) (magit-goto-line old-line) (magit-goto-section old-section)) (magit-refresh-marks-in-buffer buf))) @@ -653,14 +658,13 @@ pushed. ;;; Resetting (defun magit-reset-soft (target) - (interactive (list (read-string "Reset history to: " "HEAD^"))) + (interactive (list (magit-commit-at-point))) (magit-run "git" "reset" "--soft" target)) (defun magit-reset-hard (target) - (interactive (list (read-string "Reset working tree (and history) to: " - "HEAD"))) + (interactive (list (magit-commit-at-point))) (if (yes-or-no-p - (format "Hard reset to %s and throw away all uncommitted changes? " + (format "Hard reset and throw away all uncommitted changes? " target)) (magit-run "git" "reset" "--hard" target))) @@ -757,11 +761,13 @@ pushed. (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 "^") 'magit-log-commit) + (define-key map (kbd "a") 'magit-apply-commit) + (define-key map (kbd "v") 'magit-revert-commit) + (define-key map (kbd "H") 'magit-checkout-commit) (define-key map (kbd "L") 'magit-browse-branch-log) + (define-key map (kbd "x") 'magit-reset-soft) + (define-key map (kbd "X") 'magit-reset-hard) (define-key map (kbd "q") 'magit-quit) map)) @@ -784,7 +790,7 @@ 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 +`\\[magit-apply-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 @@ -811,7 +817,7 @@ the current line into your working tree. (interactive) (magit-run "git" "revert" "--no-commit" (magit-commit-at-point))) -(defun magit-pick-commit () +(defun magit-apply-commit () (interactive) (magit-run "git" "cherry-pick" "--no-commit" (magit-commit-at-point))) diff --git a/magit.texi b/magit.texi index a11cc2c1..bb4c7712 100644 --- a/magit.texi +++ b/magit.texi @@ -149,26 +149,28 @@ You can move point to a commit and then cause various things to happen with it. 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 -history buffer. +commit. -Typing @kbd{R} will revert the current commit in your working tree and +Typing @kbd{v} will revert the current commit in your working tree and staging area. Thus, it will apply the changes made by that commit in reverse. This is obviously useful to cleanly undo changes that turned out to be wrong. -Typing @kbd{P} will apply the current commit in the normal way. This +Typing @kbd{a} will apply the current commit in the normal way. This is useful when you are browsing the history of some other branch and you want to `cherry-pick' some changes from it 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{C} will switch your working tree to the current commit. +Typing @kbd{H} will switch your working tree to the current commit. You can also mark the current commit by typing @kbd{.}. Once you have marked a commit, you can show the differences between it and the current commit by typing @kbd{=}. +Finally, typing @kbd{^} will use the current commit as the new +starting point of the history buffer. + @node Resetting @chapter Resetting From b4efebca2f8fad39a0b3d08b698922095c74af9e Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sat, 16 Aug 2008 21:52:33 +0300 Subject: [PATCH 03/14] Remove magit-log-mode, use generic magit-mode instead. * magit.el (magit-mode): Truncate lines. --- magit.el | 57 ++++---------------------------------------------------- 1 file changed, 4 insertions(+), 53 deletions(-) diff --git a/magit.el b/magit.el index 2271fded..f1020618 100644 --- a/magit.el +++ b/magit.el @@ -355,7 +355,8 @@ pushed. (setq buffer-read-only t) (setq major-mode 'magit-mode mode-name "Magit" - mode-line-process "") + mode-line-process "" + truncate-lines t) (use-local-map magit-mode-map) (run-mode-hooks 'magit-mode-hook)) @@ -753,57 +754,7 @@ pushed. (open-line 1) (insert (format "(%s): " fun))))))))) -;;; History browsing - -(defvar magit-log-mode-map - (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 "^") 'magit-log-commit) - (define-key map (kbd "a") 'magit-apply-commit) - (define-key map (kbd "v") 'magit-revert-commit) - (define-key map (kbd "H") 'magit-checkout-commit) - (define-key map (kbd "L") 'magit-browse-branch-log) - (define-key map (kbd "x") 'magit-reset-soft) - (define-key map (kbd "X") 'magit-reset-hard) - (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. \\ - -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-apply-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)) +;;; Commit browsing (defun magit-commit-at-point () (let* ((info (get-text-property (point) 'magit-info)) @@ -867,7 +818,7 @@ the current line into your working tree. (let* ((topdir (magit-get-top-dir default-directory))) (switch-to-buffer "*magit-log*") (setq default-directory topdir) - (magit-log-mode) + (magit-mode) (let ((inhibit-read-only t)) (save-excursion (erase-buffer) From 5072939384526d91150bd55364775dd700820607 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sat, 16 Aug 2008 21:59:30 +0300 Subject: [PATCH 04/14] * magit.el (magit-update-status): Bring back Unpushed commit. --- magit.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/magit.el b/magit.el index f1020618..4c718ef0 100644 --- a/magit.el +++ b/magit.el @@ -469,10 +469,11 @@ pushed. (magit-insert-section 'staged "Staged changes:" 'magit-wash-diff "git" "diff" "--cached") - (magit-insert-section 'unpushed - "Recent commits:" 'magit-wash-log - "git" "log" "--graph" "--max-count=10" - "--pretty=oneline")) + (if remote + (magit-insert-section 'unpushed + "Unpushed commits:" 'magit-wash-log + "git" "log" "--graph" "--pretty=oneline" + (format "%s/%s..HEAD" remote branch)))) (magit-goto-line old-line) (magit-goto-section old-section)) (magit-refresh-marks-in-buffer buf))) From 7d0da4a5bd5e686711ea57269b037f910bcc4694 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 00:37:50 +0300 Subject: [PATCH 05/14] Redone diffing, logging, and resetting. Provide generic support for revisions and ranges of revisions as arguments to interactive functions. --- magit.el | 239 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 156 insertions(+), 83 deletions(-) diff --git a/magit.el b/magit.el index 4c718ef0..be540f80 100644 --- a/magit.el +++ b/magit.el @@ -119,6 +119,78 @@ (put-text-property (line-beginning-position) (line-end-position) 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 ((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%s: " + op + (if def-beg + (format " (default %s)" + (magit-rev-describe def-beg)) + "")) + def-beg))) + (if (not beg) + nil + (let ((end (magit-read-rev + (format "%s end%s: " + op + (if def-end + (format " (default %s)" + (magit-rev-describe def-end)) + "")) + 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)))))) + ;;; Sections (defun magit-insert-section (section title washer cmd &rest args) @@ -236,17 +308,17 @@ (define-key map (kbd "S") 'magit-stage-all) (define-key map (kbd "u") 'magit-unstage-thing-at-point) (define-key map (kbd "i") 'magit-ignore-thing-at-point) - (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-diff-with-mark) - (define-key map (kbd "?") 'magit-log-commit) - (define-key map (kbd "a") 'magit-apply-commit) - (define-key map (kbd "v") 'magit-revert-commit) - (define-key map (kbd "H") 'magit-checkout-commit) - (define-key map (kbd "x") 'magit-reset-soft) - (define-key map (kbd "X") 'magit-reset-hard) + (define-key map (kbd "l") 'magit-log-head) + (define-key map (kbd "L") 'magit-log) + (define-key map (kbd "d") 'magit-diff-head) + (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 "b") 'magit-switch-branch) + (define-key map (kbd "b") 'magit-checkout) (define-key map (kbd "B") 'magit-create-branch) (define-key map (kbd "m") 'magit-manual-merge) (define-key map (kbd "M") 'magit-automatic-merge) @@ -255,11 +327,7 @@ (define-key map (kbd "P") 'magit-push) (define-key map (kbd "c") 'magit-log-edit) (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 "q") 'magit-quit) map)) (defvar magit-mode-hook nil) @@ -592,39 +660,37 @@ pushed. ;;; Branches -(defun magit-list-branches () - (magit-shell-lines "git branch -a | cut -c3-")) - -(defun magit-read-rev (prompt) - (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-checkout (rev) + (interactive (list (magit-read-rev "Switch to: "))) + (if rev + (magit-run "git" "checkout" (magit-rev-to-git rev)))) (defun magit-read-create-branch-args () - (let* ((branches (magit-list-branches)) - (cur-branch (magit-get-current-branch)) + (let* ((cur-branch (magit-get-current-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))) (defun magit-create-branch (branch parent) (interactive (magit-read-create-branch-args)) (if (and branch (not (string= branch "")) - parent (not (string= parent ""))) - (magit-run "git" "checkout" "-b" branch parent))) + parent) + (magit-run "git" "checkout" "-b" + branch + (magit-rev-to-git parent)))) ;;; Merging -(defun magit-manual-merge (branch) - (interactive (list (magit-read-rev "Manually merge from branch: "))) - (magit-run "git" "merge" "--no-ff" "--no-commit" branch)) +(defun magit-manual-merge (rev) + (interactive (list (magit-read-rev "Manually merge: "))) + (if rev + (magit-run "git" "merge" "--no-ff" "--no-commit" + (magit-rev-to-git rev)))) -(defun magit-automatic-merge (branch) - (interactive (list (magit-read-rev "Merge from branch: "))) - (magit-run "git" "merge" branch)) +(defun magit-automatic-merge (rev) + (interactive (list (magit-read-rev "Merge: "))) + (if rev + (magit-run "git" "merge" (magit-rev-to-git branch)))) ;;; Rebasing @@ -644,7 +710,9 @@ pushed. (interactive) (let ((info (magit-rebase-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" (magit-read-rev "Rebase to: ")))) (let ((cursor-in-echo-area t) (message-log-max nil)) (message "Rebase in progress. Abort, Skip, or Continue? ") @@ -659,16 +727,14 @@ pushed. ;;; Resetting -(defun magit-reset-soft (target) - (interactive (list (magit-commit-at-point))) - (magit-run "git" "reset" "--soft" target)) +(defun magit-reset-head (rev) + (interactive (list (magit-read-rev "Reset head to: "))) + (if rev + (magit-run "git" "reset" "--soft" (magit-rev-to-git rev)))) -(defun magit-reset-hard (target) - (interactive (list (magit-commit-at-point))) - (if (yes-or-no-p - (format "Hard reset and throw away all uncommitted changes? " - target)) - (magit-run "git" "reset" "--hard" target))) +(defun magit-reset-working-tree () + (if (yes-or-no-p "Discard all uncommitted changes? ") + (magit-run "git" "reset" "--hard"))) ;;; Push and pull @@ -680,7 +746,7 @@ pushed. (interactive) (magit-run "git" "push" "-v")) -;;; Commit +;;; Committing (defvar magit-log-edit-map nil) @@ -755,7 +821,7 @@ pushed. (open-line 1) (insert (format "(%s): " fun))))))))) -;;; Commit browsing +;;; Commits (defun magit-commit-at-point () (let* ((info (get-text-property (point) 'magit-info)) @@ -814,50 +880,57 @@ pushed. (magit-put-line-property 'magit-info (list 'commit commit)))) (forward-line))) -(defun magit-browse-log (head) - (interactive (list (magit-get-current-branch))) - (let* ((topdir (magit-get-top-dir default-directory))) - (switch-to-buffer "*magit-log*") - (setq default-directory topdir) - (magit-mode) - (let ((inhibit-read-only t)) - (save-excursion - (erase-buffer) - (magit-insert-section 'history (format "History of %s" head) - 'magit-wash-log - "git" "log" "--graph" "--max-count=10000" - "--pretty=oneline" head))) - (magit-refresh-marks-in-buffer (current-buffer)))) +(defun magit-log (range) + (interactive (list (magit-read-rev-range "Log" (magit-get-current-branch)))) + (if range + (let* ((topdir (magit-get-top-dir default-directory)) + (args (magit-rev-range-to-git range))) + (switch-to-buffer "*magit-log*") + (setq default-directory topdir) + (magit-mode) + (let ((inhibit-read-only t)) + (save-excursion + (erase-buffer) + (magit-insert-section 'history + (magit-rev-range-describe range "Commits") + 'magit-wash-log + "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) - (magit-browse-log (magit-read-rev "Browse history of branch: "))) - -(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))) + (magit-log "HEAD")) ;;; Diffing -(defun magit-show-diff (&rest args) - (let ((dir default-directory) - (buf (get-buffer-create "*magit-diff*"))) - (display-buffer buf) - (save-excursion - (set-buffer buf) - (setq buffer-read-only t) - (setq default-directory dir) - (let ((inhibit-read-only t)) - (erase-buffer) - (apply 'magit-insert-section 'diff nil 'magit-wash-diff - "git" "diff" args))))) +(defun magit-diff (range) + (interactive (list (magit-read-rev-range "Diff"))) + (if range + (let* ((dir default-directory) + (args (magit-rev-range-to-git range)) + (buf (get-buffer-create "*magit-diff*"))) + (display-buffer buf) + (save-excursion + (set-buffer buf) + (setq buffer-read-only t) + (setq default-directory dir) + (let ((inhibit-read-only t)) + (erase-buffer) + (magit-insert-section 'diff + (magit-rev-range-describe range "Changes") + 'magit-wash-diff + "git" "diff" args)))))) -(defun magit-diff-with-branch (branch) - (interactive (list (magit-read-rev "Diff against: "))) - (magit-show-diff branch)) +(defun magit-diff-head (rev) + (interactive (list (magit-read-rev "Diff with: "))) + (if rev + (magit-diff (cons "HEAD" rev)))) + +(defun magit-diff-with-mark () + (interactive) + (magit-diff (cons (magit-marked-object) + (magit-commit-at-point)))) ;;; Markers From 3c9bf0a0f2e2b3e695ed2877ed58d03c3fa61885 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 00:43:49 +0300 Subject: [PATCH 06/14] Make magit-reset-working-tree interactive. * magit.el (magit-reset-working-tree): Add 'interactive' form. --- magit.el | 1 + 1 file changed, 1 insertion(+) diff --git a/magit.el b/magit.el index be540f80..31a6211d 100644 --- a/magit.el +++ b/magit.el @@ -733,6 +733,7 @@ pushed. (magit-run "git" "reset" "--soft" (magit-rev-to-git rev)))) (defun magit-reset-working-tree () + (interactive) (if (yes-or-no-p "Discard all uncommitted changes? ") (magit-run "git" "reset" "--hard"))) From b74bb2d2d9295bcae09a86fe159b6902f91debb5 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 01:37:48 +0300 Subject: [PATCH 07/14] General defaulting for revisions. * magit.el (magit-commit-at-point): Added option nil-ok-p argument. (magit-default-rev): New. --- magit.el | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/magit.el b/magit.el index 31a6211d..f789eebe 100644 --- a/magit.el +++ b/magit.el @@ -191,6 +191,9 @@ (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 (defun magit-insert-section (section title washer cmd &rest args) @@ -824,13 +827,15 @@ pushed. ;;; Commits -(defun magit-commit-at-point () +(defun magit-commit-at-point (&optional nil-ok-p) (let* ((info (get-text-property (point) 'magit-info)) (commit (and info (eq (car info) 'commit) (cadr info)))) - (or commit - (error "No commit at point.")))) + (if nil-ok-p + commit + (or commit + (error "No commit at point."))))) (defun magit-revert-commit () (interactive) From e82f5da8316139b83e2cb6e7d370143ba18943ed Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 01:40:04 +0300 Subject: [PATCH 08/14] Show default when asking for a revision. * magit.el (magit-read-rev): Include default in prompt. Updated all callers to new prompt rules.. (magit-checkout): Use magit-default-rev interactively. --- magit.el | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/magit.el b/magit.el index f789eebe..5d841ee5 100644 --- a/magit.el +++ b/magit.el @@ -125,8 +125,12 @@ (magit-shell-lines "git branch -a | cut -c3-")) (defun magit-read-rev (prompt &optional def) - (let ((rev (completing-read prompt (magit-list-interesting-revisions) - nil nil nil nil def))) + (let* ((prompt (if def + (format "%s (default %s): " prompt + (magit-rev-describe def)) + (format "%s: " prompt))) + (rev (completing-read prompt (magit-list-interesting-revisions) + nil nil nil nil def))) (if (string= rev "") nil rev))) @@ -134,24 +138,11 @@ (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%s: " - op - (if def-beg - (format " (default %s)" - (magit-rev-describe def-beg)) - "")) - def-beg))) + (let ((beg (magit-read-rev (format "%s start" op) + def-beg))) (if (not beg) nil - (let ((end (magit-read-rev - (format "%s end%s: " - op - (if def-end - (format " (default %s)" - (magit-rev-describe def-end)) - "")) - def-end))) + (let ((end (magit-read-rev (format "%s end" op) def-end))) (cons beg end)))))) (defun magit-rev-to-git (rev) @@ -664,14 +655,14 @@ pushed. ;;; Branches (defun magit-checkout (rev) - (interactive (list (magit-read-rev "Switch to: "))) + (interactive (list (magit-read-rev "Switch to" (magit-default-rev)))) (if rev (magit-run "git" "checkout" (magit-rev-to-git rev)))) (defun magit-read-create-branch-args () (let* ((cur-branch (magit-get-current-branch)) (branch (read-string "Create branch: ")) - (parent (magit-read-rev "Parent: " cur-branch))) + (parent (magit-read-rev "Parent" cur-branch))) (list branch parent))) (defun magit-create-branch (branch parent) @@ -685,13 +676,13 @@ pushed. ;;; Merging (defun magit-manual-merge (rev) - (interactive (list (magit-read-rev "Manually merge: "))) + (interactive (list (magit-read-rev "Manually merge"))) (if rev (magit-run "git" "merge" "--no-ff" "--no-commit" (magit-rev-to-git rev)))) (defun magit-automatic-merge (rev) - (interactive (list (magit-read-rev "Merge: "))) + (interactive (list (magit-read-rev "Merge"))) (if rev (magit-run "git" "merge" (magit-rev-to-git branch)))) @@ -713,9 +704,9 @@ pushed. (interactive) (let ((info (magit-rebase-info))) (if (not info) - (let ((rev (magit-read-rev "Rebase to: "))) + (let ((rev (magit-read-rev "Rebase to"))) (if rev - (magit-run "git" "rebase" (magit-read-rev "Rebase to: ")))) + (magit-run "git" "rebase" rev))) (let ((cursor-in-echo-area t) (message-log-max nil)) (message "Rebase in progress. Abort, Skip, or Continue? ") @@ -731,7 +722,7 @@ pushed. ;;; Resetting (defun magit-reset-head (rev) - (interactive (list (magit-read-rev "Reset head to: "))) + (interactive (list (magit-read-rev "Reset head to"))) (if rev (magit-run "git" "reset" "--soft" (magit-rev-to-git rev)))) @@ -929,7 +920,7 @@ pushed. "git" "diff" args)))))) (defun magit-diff-head (rev) - (interactive (list (magit-read-rev "Diff with: "))) + (interactive (list (magit-read-rev "Diff with"))) (if rev (magit-diff (cons "HEAD" rev)))) From 8b481fb716a7df73b50b52ec5cf27b9a47ed3d2b Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 01:40:39 +0300 Subject: [PATCH 09/14] Removed magit-checkout-commit. --- magit.el | 4 ---- 1 file changed, 4 deletions(-) diff --git a/magit.el b/magit.el index 5d841ee5..302cd3f0 100644 --- a/magit.el +++ b/magit.el @@ -836,10 +836,6 @@ pushed. (interactive) (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 () (interactive) (magit-browse-log (magit-commit-at-point))) From 6a0b8c83e4020e8809dd063324ba19fce67e2738 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 02:27:00 +0300 Subject: [PATCH 10/14] Declare submodes of buffer, now that all of them are in magit-mode. * magit.el (magit-mode-init): New. (magit-status, magit-diff, magit-log): Use it. (magit-find-buffer, magit-find-status-buffer): Look at magit-submode. --- magit.el | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/magit.el b/magit.el index 302cd3f0..89c6bd3d 100644 --- a/magit.el +++ b/magit.el @@ -327,10 +327,14 @@ (defvar magit-mode-hook nil) (put 'magit-mode 'mode-class 'special) -(put 'magit-marked-object 'permanent-local t) (defvar magit-marked-object nil) (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 () ;;; XXX - the formatting is all screwed up because of the \\[...] @@ -422,6 +426,11 @@ pushed. (use-local-map magit-mode-map) (run-mode-hooks 'magit-mode-hook)) +(defun magit-mode-init (dir submode) + (setq default-directory dir + magit-submode submode) + (magit-mode)) + ;;; Status (defun magit-wash-other-files (status) @@ -540,15 +549,19 @@ pushed. (magit-goto-section old-section)) (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)))) (dolist (buf (buffer-list)) (if (save-excursion (set-buffer buf) (and (equal default-directory topdir) - (eq major-mode 'magit-mode))) + (eq major-mode 'magit-mode) + (eq magit-submode submode))) (return buf))))) +(defun magit-find-status-buffer (&optional dir) + (magit-find-buffer 'status dir)) + (defun magit-status (dir) (interactive (list (magit-read-top-dir current-prefix-arg))) (save-some-buffers) @@ -557,8 +570,7 @@ pushed. (create-file-buffer (file-name-nondirectory (directory-file-name topdir)))))) (switch-to-buffer buf) - (setq default-directory topdir) - (magit-mode) + (magit-mode-init topdir 'status) (magit-update-status buf))) ;;; Staging @@ -879,8 +891,7 @@ pushed. (let* ((topdir (magit-get-top-dir default-directory)) (args (magit-rev-range-to-git range))) (switch-to-buffer "*magit-log*") - (setq default-directory topdir) - (magit-mode) + (magit-mode-init topdir 'log) (let ((inhibit-read-only t)) (save-excursion (erase-buffer) @@ -906,8 +917,7 @@ pushed. (display-buffer buf) (save-excursion (set-buffer buf) - (setq buffer-read-only t) - (setq default-directory dir) + (magit-mode-init dir 'diff) (let ((inhibit-read-only t)) (erase-buffer) (magit-insert-section 'diff From bf1c66ce5c49325edf7759253980290073c77f7e Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 02:32:07 +0300 Subject: [PATCH 11/14] Don't be too clever when showing default revisions. * magit.el (magit-read-rev): Do not use magit-rev-describe when formatting the default value for the prompt. This is misleading since it might use names of branches etc while in reality we are might be offering a raw commit. --- magit.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/magit.el b/magit.el index 89c6bd3d..5d6a2236 100644 --- a/magit.el +++ b/magit.el @@ -126,8 +126,7 @@ (defun magit-read-rev (prompt &optional def) (let* ((prompt (if def - (format "%s (default %s): " prompt - (magit-rev-describe def)) + (format "%s (default %s): " prompt def) (format "%s: " prompt))) (rev (completing-read prompt (magit-list-interesting-revisions) nil nil nil nil def))) From 72819bd45162c2b3e536b5cce0909fb2be5b5d8d Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 02:35:05 +0300 Subject: [PATCH 12/14] Make 'd' diff against working tree, not HEAD. * magit.el (magit-diff-head, magit-diff-working-tree): Renamed former to latter. Use single revision when calling magit-diff. --- magit.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/magit.el b/magit.el index 5d6a2236..0f3f84f1 100644 --- a/magit.el +++ b/magit.el @@ -306,7 +306,7 @@ (define-key map (kbd "=") 'magit-diff-with-mark) (define-key map (kbd "l") 'magit-log-head) (define-key map (kbd "L") 'magit-log) - (define-key map (kbd "d") 'magit-diff-head) + (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) @@ -924,10 +924,10 @@ pushed. 'magit-wash-diff "git" "diff" args)))))) -(defun magit-diff-head (rev) +(defun magit-diff-working-tree (rev) (interactive (list (magit-read-rev "Diff with"))) (if rev - (magit-diff (cons "HEAD" rev)))) + (magit-diff rev))) (defun magit-diff-with-mark () (interactive) From 6538ce4e4aabbdbc68c24ed1efbd1c05921fbd4a Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 02:35:54 +0300 Subject: [PATCH 13/14] Manual improvements and updates. --- magit.texi | 120 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 51 deletions(-) diff --git a/magit.texi b/magit.texi index bb4c7712..0797e47a 100644 --- a/magit.texi +++ b/magit.texi @@ -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 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 @chapter Status Running @kbd{M-x magit-status} displays the main interface of Magit, -the status buffer. Almost all operations are initiated with single -letter keystrokes from that buffer. +the status buffer. You can have multiple status buffers active at the same time, each 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 C-c} in that buffer to commit the staged changes. -Typing @kbd{C} will also pop up the change description buffer, but it -will also try to insert a ChangeLog-style entry for the change that -point is in. +Typing @kbd{C} will also pop up the change description buffer, but in +addition, it will try to insert a ChangeLog-style entry for the change +that point is in. If the current branch is associated with a remote repository, the status buffer will show a fourth section, named @emph{Unpushed @@ -137,39 +142,46 @@ Pulling} for more information. @node History @chapter History -To browse the repository history, type @kbd{l} or @kbd{L} in the -status buffer. Typing @kbd{l} will show the history starting from the -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. +To show the repository history of your current head, type @kbd{l}. 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 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 -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 commit. -Typing @kbd{v} will revert the current commit in your working tree and -staging area. Thus, it will apply the changes made by that commit in -reverse. This is obviously useful to cleanly undo changes that turned -out to be wrong. +Typing @kbd{a} will apply the current commit to your working tree and +staging area. This is useful when you are browsing the history of +some other branch and you want to `cherry-pick' some changes from it +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{a} will apply the current commit in the normal way. This -is useful when you are browsing the history of some other branch and -you want to `cherry-pick' some changes from it 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{v} will revert the current commit. Thus, it will apply +the changes made by that commit in reverse. This is obviously useful +to cleanly undo changes that turned out to be wrong. -Typing @kbd{H} 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 -marked a commit, you can show the differences between it and the -current commit by typing @kbd{=}. +You can mark the current commit by typing @kbd{.}. Some commands, +such as @kbd{=}, will use the current commit and the marked commit as +implicit arguments. Other commands will offer the marked commit as a +default when prompting for their arguments. -Finally, typing @kbd{^} will use the current commit as the new -starting point of the history buffer. +@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 @chapter Resetting @@ -178,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 head to an earlier commit and start over. -If you have published your history already, rewriting history in this -way can be confusing and should be avoided. However, rewriting your -local history is fine and it is often cleaner to fix mistakes this way -than by reverting commits (with @kbd{R} in the history buffer, for -example). +If you have published your history already, rewriting it in this way +can be confusing and should be avoided. However, rewriting your local +history is fine and it is often cleaner to fix mistakes this way than +by reverting commits (with @kbd{R}, for example). -Magit gives you two ways to reset your current head: soft and hard. -Type @kbd{x} to do a soft reset. This will change the current head to -the commit that you specify, but your current working tree and staging -area will not be touched. This is useful to redoing the last commit -to correct the commit message, for example. +Typing @kbd{x} will ask for a revision and reset your current head to +it. No changes will be made to your working tree and staging area. +Thus, the @emph{Staged changes} section in the status buffer will show +the changes that you have removed from your commit history. You can +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 -the commit you specify and will check it out so that your working tree -and staging area will match it. In other words, a hard reset will -throw away the history completely, which can be useful to abort -experimental changes (like merging a branch just to see what happens). +Typing @kbd{x} while point is in a line that describes a commit will +offer this commit as the default revision to reset to. Thus, you can +move point to one of the commits in the @emph{Unpushed commits} +section and hit @kbd{x RET} to reset your current head to it. -In particular, doing a hard reset to HEAD will have no effect on the -current head, but it will reset your working tree and staging area -back to the last committed state. +Type @kbd{X} to reset your working tree and staging area to the most +recently committed state. This will discard your local modifications, +so be careful. @node Branching and Merging @chapter Branching and Merging 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 -new branch and check it out immediately, type @kbd{B}. +You can switch to a different branch by typing @kbd{b}. This will +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 -@kbd{d} and then specify the branch to compare with. +Similar to @kbs{x}, typing @kbd{b} while point is at a commit +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 manual merge will apply all changes to your working tree and staging @@ -219,9 +237,9 @@ Type @kbd{m} to initiate a manual merge, and type @kbd{M} for a automatic merge. 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 -appropriate when you are on a feature branch and want to catch up with -the master, say. +want to review and test before even committing it. A automatic merge +is appropriate when you are on a feature branch and want to catch up +with the master, say. 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 From dfa35cb2e037df3f248a061d795f02a479a687b5 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 17 Aug 2008 02:43:39 +0300 Subject: [PATCH 14/14] Updated NEWS. --- NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS b/NEWS index 7408c538..d4d14951 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,10 @@ 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 well.