Use Magit API to rebase to closest branch

  |   Source

My workflow in Git is,

  • Create a new feature branch based on main branch
  • Add some small commits into feature branch
  • Rebase feature branch interactively

The final rebase step happens a lot.

So I could use Magit api magit-rebase-interactive to speed up it.

The key is to analyze output of git log --decorate --oneline to find the main branch commit.

Code,

(defun my-git-extract-based (target)
  "Extract based version from TARGET."
  (replace-regexp-in-string "^tag: +"
                            ""
                            (car (nreverse (split-string target ", +")))))

(defun my-git-rebase-interactive (&optional user-select-branch)
  "Rebase interactively on the closest branch or tag in git log output.
If USER-SELECT-BRANCH is not nil, rebase on the tag or branch selected by user."
  (interactive "P")
  (let* ((log-output (shell-command-to-string "git --no-pager log --decorate --oneline -n 1024"))
         (lines (split-string log-output "\n"))
         (targets (delq nil
                        (mapcar (lambda (e)
                                  (when (and (string-match "^[a-z0-9]+ (\\([^()]+\\)) " e)
                                             (not (string-match "^[a-z0-9]+ (HEAD " e)))
                                    (match-string 1 e))) lines)))
         based)
    (cond
     ((or (not targets) (eq (length targets) 0))
      (message "No tag or branch is found to base on."))
     ((or (not user-select-branch)) (eq (length targets) 1)
      ;; select the closest/only tag or branch
      (setq based (my-git-extract-based (nth 0 targets))))
     (t
      ;; select the one tag or branch
      (setq based (my-git-extract-based (completing-read "Select based: " targets)))))

    ;; start git rebase
    (when based
      (magit-rebase-interactive based nil))))

Screencast:

magit-rebase-api.gif

Comments powered by Disqus