How to change repo with magit emacs?
Asked Answered
P

6

16

I need to work with a few different git repositories. How to switch between them using magit? Magit allows me to choose a directory when I just start it.. But it is not clear for me how to switch to another repo if required. I've looked at magit cheatsheet and docs but haven't found an answer. Thanks.

Phagocyte answered 21/2, 2014 at 10:34 Comment(1)
Just use dired or bookmark to switch to other file. Then call magit from there.Lightship
S
1

magit have changed a few things, so here is an updated version that worked for me in 2024 of the accepted answer

(let ((depth 1)) ;; set the depth of where .git will be at the deepest to 1, i.e. somesubproject/.git/ and .git/ will be searched. if set to 0, only .git/ directly after root will be listed
(eval-after-load "projectile"
  '(progn (setq magit-repository-directories (mapcar (lambda (dir)
                                                       (cons (substring dir 0 -1) depth)
                                                       )
                                       (remove-if-not (lambda (project)
                                                        (file-directory-p (concat project "/.git/")))
                                                      projectile-known-projects))))
         )))

The things changed:

  • magit-repo-dirs changed to magit-repositories-directories, and the schema of the variable changed to a list of element with (DIRECTORY . DEPTH) form, where depth refers maximum depth to scan of .git/, start with 1, with .git/ directly under root
  • now there is a magit-list-repositories command. it uses magit-repositories-directories, and that gives a more detailed buffer for you to choose repos from(including name, version and path).

edit: I changed from (projectile-relevent-known-projects) to projectile-known-projects. the former don't include some projects, such as the current one.

Softener answered 17/4 at 15:18 Comment(0)
S
22

You can call magit-status with prefix-arg (C-u), it will prompt you for git repository. So if you keybinding for magit-status is C-xg, you can do C-uC-xg, it will prompt for git repo.

You can also set the variable magit-repo-dirs to a directory (do C-hfmagit-repo-dirsRET to know more) and it will prompt you for all git repositories in magit-repo-dirs.

If you use projectile you can use the fact that it remembers your project directories and use it populate magit-repo-dirs, I have this in my init file to achieve this

(eval-after-load "projectile" 
  '(progn (setq magit-repo-dirs (mapcar (lambda (dir)
                                         (substring dir 0 -1))
                                       (remove-if-not (lambda (project)
                                                        (file-directory-p (concat project "/.git/"))) 
                                                      (projectile-relevant-known-projects))))

         (setq magit-repo-dirs-depth 1)))

The code above is executed after projectile is loaded. It gets the list of projects known to projectile by doing (projectile-relevant-known-projects), iterates through them and adds the projects that have .git/ folder to magit-repo-dirs, it also sets magit-repo-dirs-depth to 1 so magit looks for git repos only in the top directories.

Sawyers answered 21/2, 2014 at 10:58 Comment(0)
V
6

I've found that if you use projectile, the easiest is to just set the following:

(setq projectile-switch-project-action 'projectile-vc)

Now you can use C-p p s (projectile-switch-project) and it will then immediately call projectile-vc, which if you have magit installed just calls magit-status in the project root. Simple!

Volotta answered 22/8, 2014 at 22:0 Comment(0)
G
3

There is a nice package by John Wiegley called "Springboard" that might be useful for you.

https://github.com/jwiegley/springboard

It depends on helm and/or ido, and it allows you to execute arbitrary commands on the basis of files that might be in a different directory to the whichever file is currently in the active buffer. It's a little difficult to illustrate it in a non-verbose way (the README explains it well), but just to use your question as an example:

  • Assume you are working on a file 1.el that is part of a git repo but you want to run magit-status for a separate file 2.el which is in another repo altogether.

  • Using M-x springboard for helm or ido-switch-buffer for ido
    gives you a list of candidate files.

  • By focussing on 2.el (but not selecting it) you can then invoke
    arbitrary commands as if you were working within that file's directory.

  • So, if you were to focus on 2.el and then call magit-status from the candidate list, you would get the normal magit-status window for the repo associated with the file 2.el and then once you have finished working with that you can just exit magit and 1.el will be the active buffer and everything will be as it was before springboard was invoked.

It is extremely useful.

Guanabara answered 22/2, 2014 at 19:3 Comment(0)
H
1

Magit uses current working directory of your current buffer when you execute magit-status. If other answers fail, here is inefficient but always working alternative:

  1. Close magit current buffers (if any) (q)
  2. Change directory to the one with your repo (M-x cd)
  3. Start magit again (M-x magit-status)

(Inefficient because magit will be restarted)

Hindoo answered 14/2, 2020 at 13:48 Comment(0)
S
1

magit have changed a few things, so here is an updated version that worked for me in 2024 of the accepted answer

(let ((depth 1)) ;; set the depth of where .git will be at the deepest to 1, i.e. somesubproject/.git/ and .git/ will be searched. if set to 0, only .git/ directly after root will be listed
(eval-after-load "projectile"
  '(progn (setq magit-repository-directories (mapcar (lambda (dir)
                                                       (cons (substring dir 0 -1) depth)
                                                       )
                                       (remove-if-not (lambda (project)
                                                        (file-directory-p (concat project "/.git/")))
                                                      projectile-known-projects))))
         )))

The things changed:

  • magit-repo-dirs changed to magit-repositories-directories, and the schema of the variable changed to a list of element with (DIRECTORY . DEPTH) form, where depth refers maximum depth to scan of .git/, start with 1, with .git/ directly under root
  • now there is a magit-list-repositories command. it uses magit-repositories-directories, and that gives a more detailed buffer for you to choose repos from(including name, version and path).

edit: I changed from (projectile-relevent-known-projects) to projectile-known-projects. the former don't include some projects, such as the current one.

Softener answered 17/4 at 15:18 Comment(0)
H
0

Updating on the accepted answer, here is the code that worked for me in Emacs 25. remove-if-not was not a known function, for some reason.

(eval-after-load "projectile" 
'(progn (setq magit-repo-dirs (mapcar (lambda (dir)
(substring dir 0 -1))
(seq-remove (lambda (project)
          (not (file-directory-p (concat project "/.git/"))))
        (projectile-relevant-known-projects))))
(setq magit-repo-dirs-depth 1)))
Headcloth answered 15/11, 2020 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.