Function: magit-branch-delete

magit-branch-delete is an autoloaded, interactive and byte-compiled function defined in magit-branch.el.

Signature

(magit-branch-delete BRANCHES &optional FORCE)

Documentation

Delete one or multiple branches.

If the region marks multiple branches, then offer to delete those, otherwise prompt for a single branch to be deleted, defaulting to the branch at point.

Require confirmation when deleting branches is dangerous in some way. Option magit-no-confirm can be customized to not require confirmation in certain cases. See its docstring to learn why confirmation is required by default in certain cases or if a prompt is confusing.

Key Bindings

Source Code

;; Defined in ~/.emacs.d/elpa/magit-20260411.1452/magit-branch.el
;;;###autoload
(defun magit-branch-delete (branches &optional force)
  "Delete one or multiple branches.

If the region marks multiple branches, then offer to delete
those, otherwise prompt for a single branch to be deleted,
defaulting to the branch at point.

Require confirmation when deleting branches is dangerous in some
way.  Option `magit-no-confirm' can be customized to not require
confirmation in certain cases.  See its docstring to learn why
confirmation is required by default in certain cases or if a
prompt is confusing."
  ;; One would expect this to be a command as simple as, for example,
  ;; `magit-branch-rename'; but it turns out everyone wants to squeeze
  ;; a bit of extra functionality into this one, including myself.
  (interactive
    (let ((branches (magit-region-values 'branch t))
          (force current-prefix-arg))
      (if (length> branches 1)
          (magit-confirm t nil "Delete %d branches" nil branches)
        (setq branches
              (list (magit-read-branch-prefer-other
                     (if force "Force delete branch" "Delete branch")))))
      (cond-let
        (force)
        [[unmerged (seq-remove #'magit-branch-merged-p branches)]]
        ((magit-confirm 'delete-unmerged-branch
           "Delete unmerged branch %s"
           "Delete %d unmerged branches"
           'noabort unmerged)
         (setq force branches))
        ((setq branches (cl-set-difference branches unmerged :test #'equal)))
        ((user-error "Abort")))
      (list branches force)))
  (let ((refs (mapcar #'magit-ref-fullname branches)))
    ;; If a member of refs is nil, that means that
    ;; the respective branch name is ambiguous.
    (when-let ((ambiguous (seq-filter #'null refs)))
      (user-error
       "%s ambiguous; please cleanup using git directly"
       (let ((len (length ambiguous)))
         (cond
           ((= len 1)
            (format "%s is" (seq-find #'magit-ref-ambiguous-p branches)))
           ((= len (length refs))
            (format "These %s names are" len))
           ((format "%s of these names are" len))))))
    (cond
      ((string-match "^refs/remotes/\\([^/]+\\)" (car refs))
       (let* ((remote (match-str 1 (car refs)))
              (offset (1+ (length remote))))
         (cond
           ((magit-confirm 'delete-branch-on-remote
              (list "Deleting local %s.  Also delete on %s"
                    (magit-ref-fullname (car branches))
                    remote)
              (list "Deleting %d local refs.  Also delete on %s"
                    (length refs)
                    remote)
              'noabort refs)
            ;; The ref may actually point at another rev on the remote,
            ;; but this is better than nothing.
            (dolist (ref refs)
              (message "Delete %s (was %s)" ref
                       (magit-rev-parse "--short" ref)))
            ;; Assume the branches actually still exist on the remote.
            (magit-run-git-async
             "push" "--delete"
             (and (or force magit-branch-delete-never-verify) "--no-verify")
             remote
             (mapcar (##concat "refs/heads/" (substring % offset)) branches))
            ;; If that is not the case, then this deletes the tracking branches.
            (set-process-sentinel
             magit-this-process
             (apply-partially #'magit-delete-remote-branch-sentinel remote refs)))
           (t
            (dolist (ref refs)
              (message "Delete %s (was %s)" ref
                       (magit-rev-parse "--short" ref))
              (magit-call-git "update-ref" "-d" ref))
            (magit-refresh)))))
      ((length> branches 1)
       (setq branches (delete (magit-get-current-branch) branches))
       (mapc #'magit-branch-maybe-delete-pr-remote branches)
       (mapc #'magit-branch-unset-pushRemote branches)
       (magit-run-git "branch" (if force "-D" "-d") branches))
      (t ; And now for something completely different.
       (let* ((branch (car branches))
              (prompt (format "Branch %s is checked out.  " branch))
              (target (magit-get-indirect-upstream-branch branch t)))
         (when (equal branch (magit-get-current-branch))
           (when (or (equal branch target)
                     (not target))
             (setq target (magit-main-branch)))
           (pcase (if (or (equal branch target)
                          (not target))
                      (magit-read-char-case prompt nil
                        (?d "[d]etach HEAD & delete" 'detach)
                        (?a "[a]bort"                'abort))
                    (magit-read-char-case prompt nil
                      (?d "[d]etach HEAD & delete" 'detach)
                      (?c (format "[c]heckout %s & delete" target) 'target)
                      (?a "[a]bort" 'abort)))
             (`detach (unless (or (equal force '(4))
                                  (member branch force)
                                  (magit-branch-merged-p branch t))
                        (magit-confirm 'delete-unmerged-branch
                          "Delete unmerged branch %s" ""
                          nil (list branch)))
                      (magit-call-git "checkout" "--detach"))
             (`target (unless (or (equal force '(4))
                                  (member branch force)
                                  (magit-branch-merged-p branch target))
                        (magit-confirm 'delete-unmerged-branch
                          "Delete unmerged branch %s" ""
                          nil (list branch)))
                      (magit-call-git "checkout" target))
             (`abort  (user-error "Abort")))
           (setq force t))
         (magit-branch-maybe-delete-pr-remote branch)
         (magit-branch-unset-pushRemote branch)
         (magit-run-git "branch" (if force "-D" "-d") branch))))))