3939; ; - renaming files from the status buffer
4040; ; - creating tags
4141; ; - fetch/pull
42- ; ; - switching branches
4342; ; - revlist browser
4443; ; - git-show-branch browser
45- ; ; - menus
4644; ;
4745
4846(eval-when-compile (require 'cl ))
@@ -397,6 +395,17 @@ the process output as a string, or nil if the git command failed."
397395 (unless newval (push " -d" args))
398396 (apply 'git-call-process-display-error " update-ref" args)))
399397
398+ (defun git-for-each-ref (&rest specs )
399+ " Return a list of refs using git-for-each-ref.
400+ Each entry is a cons of (SHORT-NAME . FULL-NAME)."
401+ (let (refs)
402+ (with-temp-buffer
403+ (apply #'git-call-process t " for-each-ref" " --format=%(refname)" specs)
404+ (goto-char (point-min ))
405+ (while (re-search-forward " ^[^/\n ]+/[^/\n ]+/\\ (.+\\ )$" nil t )
406+ (push (cons (match-string 1 ) (match-string 0 )) refs)))
407+ (nreverse refs)))
408+
400409(defun git-read-tree (tree &optional index-file )
401410 " Read a tree into the index file."
402411 (let ((process-environment
@@ -1356,6 +1365,24 @@ Return the list of files that haven't been handled."
13561365 (push (match-string 1 ) files )))
13571366 files ))
13581367
1368+ (defun git-read-commit-name (prompt &optional default )
1369+ " Ask for a commit name, with completion for local branch, remote branch and tag."
1370+ (completing-read prompt
1371+ (list* " HEAD" " ORIG_HEAD" " FETCH_HEAD" (mapcar #'car (git-for-each-ref)))
1372+ nil nil nil nil default ))
1373+
1374+ (defun git-checkout (branch &optional merge )
1375+ " Checkout a branch, tag, or any commit.
1376+ Use a prefix arg if git should merge while checking out."
1377+ (interactive
1378+ (list (git-read-commit-name " Checkout: " )
1379+ current-prefix-arg))
1380+ (unless git-status (error " Not in git-status buffer. " ))
1381+ (let ((args (list branch " --" )))
1382+ (when merge (push " -m" args))
1383+ (when (apply #'git-call-process-display-error " checkout" args)
1384+ (git-update-status-files))))
1385+
13591386(defun git-amend-commit ()
13601387 " Undo the last commit on HEAD, and set things up to commit an
13611388amended version of it."
@@ -1471,6 +1498,7 @@ amended version of it."
14711498 (define-key map " \M -\C -?" 'git-unmark-all )
14721499 ; the commit submap
14731500 (define-key commit-map " \C -a" 'git-amend-commit )
1501+ (define-key commit-map " \C -o" 'git-checkout )
14741502 ; the diff submap
14751503 (define-key diff-map " b" 'git-diff-file-base )
14761504 (define-key diff-map " c" 'git-diff-file-combined )
@@ -1491,6 +1519,7 @@ amended version of it."
14911519 `(" Git"
14921520 [" Refresh" git-refresh-status t]
14931521 [" Commit" git-commit-file t]
1522+ [" Checkout..." git-checkout t]
14941523 (" Merge"
14951524 [" Next Unmerged File" git-next-unmerged-file t]
14961525 [" Prev Unmerged File" git-prev-unmerged-file t]
0 commit comments