Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature proposal/question: basic git branches management with Helm? #63

Open
amno1 opened this issue Jul 26, 2021 · 8 comments
Open

Feature proposal/question: basic git branches management with Helm? #63

amno1 opened this issue Jul 26, 2021 · 8 comments

Comments

@amno1
Copy link
Contributor

amno1 commented Jul 26, 2021

I would like to be able to do at least some very basic branch manipulation with Helm. What I think of is a command like 'helm-ls-git-branches'. When run, this command will in usual style display all available branches in a git repo. Default (persistent) action would be to switch to a branch. This can't be a tad bit more involved if there are unstaged changes, so some flags and strategies would have to be customized by user how to deal with those (stash auto or similar). It would be nice if the command also offered an option to delete a branch, and to merge/squash marked branches and to push a marked branch or branches upstream. I was looking around on the webb, but I couldn't find any helm interface for managing branches, and I really miss the option to at least checkout branch from within the Helm interface, and to see a list of branches.

I am not sure if this should be tucked in the same app as helm-ls-git or if it should be a separate app.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented Jul 26, 2021 via email

@amno1
Copy link
Contributor Author

amno1 commented Jul 26, 2021

Why don't you hit bb from magit, it allows quick branch switching with

I am not so much of the mouse guy :). Helm is just cool, and I am sure magit is also very cool, but to be honest, I didn't used that part from magit, actually I used magit very little, I do stuff from cmd line mostly. Can that helm-completion in magit be snitched out of magit? :-) Or is it too tightly coupled with magit?

It would be cool to be ablte to do this from Helm interface. Like C-z b to show branches and then complete the one I wish to checkout, or delete it or push it to remote. Compare to helm vs. dired, magit is kind of similar to dired in this regard. I don't know, maybe I am wrong, just idea. I was coding a bit last night and was trying to adapt the code in hlem-ls-git, but I have never written a helm addon som I am not really at home with how everything hangs together, with all those transformer funcitons and sources and what not :).

I hacked this to list branches, was not a big deal:

(defun helm-ls-git-branches (&optional arg)
  "List branches on local or remote repository.

If `arg' is nil it will show only local branches (i.e. the command 
\"git branch\").

If `arg' has value 'all then it will fetch all remote branches,
  tracked and untracked (\"git ls-remote --heads\").

If `arg' has value 't it will show all tracked branches as of
\"git branch -r\"."
  (message "K: %s" arg)
  (helm-aif (helm-ls-git-root-dir)
      (with-helm-default-directory it
        (split-string
         (with-output-to-string
           (with-current-buffer standard-output
             (cond ((null arg)
                    (insert (call-process "git" nil t nil "branch")))
                   ((equal arg 'all)
                    (insert (call-process "git" nil t nil "ls-remote"
                                          "--heads"))
                    (goto-char (point-min))
                    (when (search-forward "From" (line-end-position) t 1)
                      (replace-match "Branches for remote repository:"))
                    (goto-char (point-min))
                    (while (search-forward "refs/heads/" nil t)
                      (replace-match ""))
                    (when (search-backward "?^@" nil t)
                      (replace-match "")))
                   (arg
                    (insert (call-process "git" nil t nil "branch" "-r"))))
             (buffer-substring-no-properties (goto-char (point-min))
                                             (line-end-position)))) "\n" t))))

But I am not sure how to hook it up into the helm interface. I would like to reuse some code from helm-ls-git, but branches can't share same screen with files, they need their own screen, so I was not sure if to build a separate app, or to hack on ls-git. At least while I am playing, I'll play with it in ls-git. The code above is not final, lists need cleanup. I am currently reading J.K blog: https://kitchingroup.cheme.cmu.edu/blog/2015/01/24/Anatomy-of-a-helm-source/ to see if I can hook-up things together.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented Jul 27, 2021 via email

@amno1
Copy link
Contributor Author

amno1 commented Jul 27, 2021

Will show you soon, it should not be that hard, not the time right now ;-)

hehe ... I have figured it out, took me about two hours, but includes reading all J.K helm articles and feeding 3 months old baby at same time :). I can now list branches and do the selection, have yet to see how to implement actions. I should have looked into less convoluted app, ls-git is a slightly bit complex to start learning helm apps, but it wasn't that bad.

Yes but it is already implemented by helm-mode, why reinvent the wheel
while Magit is already providing this?

Just a convenience, why opening magit just to switch a branch? Can as well do from M-!. But it is just slightly more convenient to hit say C-z b and complete a branch to check out. Just my personal preference. Also, not much of reinventing the wheel, you have already done it in helm-ls-git, I have just copied and slightly modified stuff to add 3 extra shell commands, nothing spectacular :). I am just not familiar with Helm framework.

I have added 3 new iterative commands, rest is mostly just modified and reused code from helm-ls-git:


;;;###autoload
(defun helm-git-local-branches (&optional arg)
  (interactive "p")
  (let ((helm-ff-default-directory
         (or helm-ff-default-directory
             default-directory)))
    (when (and arg (not (helm-git-root-dir)))
      (error "Not inside a Git repository"))
    (helm :sources (helm-git--build-local-source)
          :ff-transformer-show-only-basename nil
          :truncate-lines helm-buffers-truncate-lines
          :buffer "*helm branches*")))

;;;###autoload
(defun helm-git-remote-branches (&optional arg)
  (interactive "p")
  (let ((helm-ff-default-directory
         (or helm-ff-default-directory
             default-directory)))
    (when (and arg (not (helm-git-root-dir)))
      (error "Not inside a Git repository"))
    (helm :sources (helm-git--build-remote-source)
          :ff-transformer-show-only-basename nil
          :truncate-lines helm-buffers-truncate-lines
          :buffer "*helm branches*")))


;;;###autoload
(defun helm-git-tracked-branches (&optional arg)  <-- horrible name, need better name for this
  (interactive "p")
  (let ((helm-ff-default-directory
         (or helm-ff-default-directory
             default-directory)))
    (when (and arg (not (helm-git-root-dir)))
      (error "Not inside a Git repository"))
    (helm :sources (helm-git--build-tracked-source)
          :ff-transformer-show-only-basename nil
          :truncate-lines helm-buffers-truncate-lines
          :buffer "*helm branches*")))

I am not done yet as said, I have removed checks and fluff while I am testing it.

If you think helm-ls-git can do some branches too, I'll rename stuff to helm-ls-git prefix. If you don't think it is something to have, I'll make a small standalone helm app. I would prefer it to be part of helm-ls-git, but I am ok if you don't want it. I understand if you don't see this as something for helm-ls-git.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented Jul 27, 2021 via email

@amno1
Copy link
Contributor Author

amno1 commented Jul 27, 2021

Sure.

@thierryvolpiatto
Copy link
Member

Rethinking at it, it is indeed cool to have some git branch management for non Magit users, I discover Vc provides nothing for this (or I missed something?) so I started writing some basic stuff for branches.

@amno1
Copy link
Contributor Author

amno1 commented Aug 28, 2021

https://github.com/amno1/helm-git-branch

It is not finished yet because of lack of time so I haven't published it in Melpa, but switching local branches is operational. My plan is to add functionality to create new branch, similar as to what helm does with new files (it is just to git checkout -b branch-name) and to add functionality to pull/fetch remote branches. I meant to publish in Melpa after I add those, but if you want to include it in Helm, it's ok too.

This isn't just for non-magit users. What I did is automation. This works very well with magit or without magit. It just saves some time with a common case which we probably all do from time to time.

Magit is cool, but it is 1:1 with git. It does not do any automation for switching branches. I mentioned that it would be nice to have it on emacs-devel but Jonas never answered on that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants