¶What will we learn?
In this episode I’m going to show you the basics of how to use the preeminent Git interface for Emacs called Magit!
We’ll set it up in a basic Emacs configuration and then take a tour of the main user interface to see what functionality we have at our disposal.
This is the first video in a series about Magit where I’ll show you how to do all important source control tasks through its highly efficient interface. Once you learn Magit, you’ll never want to use Git on the command line again!
The only expectation in this series is that you have a basic understanding of how to use Git to create commits and use branches. If you are a beginner to Git, let me know in the comments and I’ll consider making a video series covering the basics of using it!
Let’s get started!
¶What is Magit?
Magit is a Git “porcelain”, or in other words it’s a user-friendly interface for the Git source control tool.
It provides helpful interfaces for many operations you might want to do with Git, both common and advanced:
- Creating and amending commits
- Managing and merging branches
- Pulling from and pushing to remotes
- Reading commit logs and “blaming” source files
- Using the reflog
…and much more!
No matter whether you are a beginner or advanced user of Git, Magit is going to make your workflow a lot more efficient and enjoyable!
Check out the Magit manual for more information.
The easiest way to install Magit is with
package.el. If you have
use-package set up, you merely need to include this in your Emacs configuration:
(use-package magit :ensure t)
Other installation approaches are covered in the Magit manual’s Installation section.
If you want to use Vim-style keybindings with Magit, all you need is evil-collection and this bit of configuration:
(use-package evil-collection :ensure t :after evil :init (evil-collection-init))
¶The Status Interface
The primary interface you will use to interact with Git repositories is the status interface. It gives you an overview of the current state of your repository and provides key bindings for quickly launching all of the operations you might want to perform.
You can launch the status interface with the
magit-status command which we’ve bound to
C-x g in the configuration snippet above.
When you launch this command, it will look for a Git repository associated with the current value of
default-directory which is typically the directory containing the file that the selected buffer is associated with. This makes it really fast to get a status view for the Git repository for the project you’re currently working on!
If a Git directory can’t be identified, you will be prompted for a path to a directory containing a Git repository.
The status buffer can be closed with the
q key. Typically you should close it once you’re done viewing it, but if you happen to switch to another buffer and make changes to a file, the status buffer might not reflect the new state of the repository.
In this case you can press the
g key when you switch back to the status buffer to run
magit-refresh so that all sections are up to date!
magit-status interface is composed of a number of sections that display information about the Git repository:
This section tells you which commit is currently the “HEAD” of 3 important locations:
- Head: The current local branch
- Merge / Rebase: The branch/remote where changes are usually pulled from (the prefix depends on whether you merged or rebased from this location last)
- Push: The branch/remote where changes are usually being pushed to
It also gives you information on the following:
- The latest tag created and the number of commits between that and
- Errors from the previous Git operation, usually when there are issues during a pull or push
This section displays the list of files under the repository directory that are not checked in to source control. This section is useful for 2 purposes:
- Discovering any new files that you need to add to your commit
- Identifying files that need to be added to your
Keep in mind that if you edit your
.gitignore file without closing the status buffer first, you might need to refresh it with
magit-refresh before the unwanted files are removed from this list!
This section displays the list of tracked files which have been changed since the last commit.
You can expand a file to view the changes it contains using the
TAB key (
magit-section-toggle). The changes will be displayed in a diff style to show the previous and new state of the changed lines. You can also open/close the individual diff sections using
This section may also show parts of your code with merge conflicts when you are running a merge operation. We’ll talk more about this in a later video.
This section displays the list of tracked files with changes that have been “staged”, meaning that they’re marked for inclusion into the next commit that the user creates.
Like the unstaged changes view, you can press
TAB to expand/collapse the files and their diff “hunks”.
Keep in mind that when you’ve staged a change, the associated hunk will move from the unstaged changes view to the staged changes view, you won’t see the same change in both!
Note that we’re not going to talk about staging/unstaging changes yet in this video, we will discuss it in the next video where we talk about creating commits!
This section displays the list of “stashes” created with the
git stash command. These are basically just diffs of changes that are saved to be used later without being committed to the repository.
Unfortunately stashes can’t be expanded with
TAB but you can press
Enter on a stash entry to take a look at the list of changes that it contains.
This section displays the list of commits in the local branch that haven’t been pushed to the usual remote branch. It’s very useful for keeping track of the work you’ve been doing which hasn’t been merged yet!
You might not see this section if you haven’t pushed the local branch anywhere yet!
This section displays changes from the remote branch which haven’t been merged or rebased into the local branch. This section will usually be populated when you fetch the latest commits from the remote branch and Git detects that there is a deviation in the commit histories that needs to be merged.
This section displays changes from the remote branch which haven’t been pulled into the local branch. This indicates that there are new commits that can be pulled cleanly into the local branch without merging.
Magit has some very efficient movement key bindings set up by default:
C-p: Move forward and backward by line (
These bindings should come as no surprise as they mirror the default line movement key bindings in Emacs
p: Move forward and backward by visible section (
These bindings are useful
M-p: Move forward and backward by section “sibling” (
^: Move to the parent of the current section (
¶The Command Panel
In the status buffer, there are many quick command bindings that you will want to learn to make your day-to-day Git operations incredibly efficient.
The easiest way to learn these bindings is to open Magit’s Transient panel by pressing
? (question mark).
This panel lists all of the operations you can perform and the prefix keys that you can press to invoke them.
Usually when you press one of the letters listed here, another sub-panel will pop up with more command prefixes and also options which can be configured starting with the
- (hyphen) key.
Any of these panels can be cancelled with
Keep in mind that if you use
evil-collection to enable Vim-style keybindings, the prefix keys for some of these commands might be changed from the defaults!
¶Our First Commit!
Since I want to make sure you come away from this episode with something actionable to use, I’m going to jump ahead a bit and show you how to make your first commit with Magit!
In this example, we’ve already got an existing repository cloned locally so all we need to do is run
M-x magit-status from within a buffer inside of that repository to call up the status interface that we talked about before.
Since we’ve already got a file with unstaged changes, we can move our cursor to the line that represents the changed file and then press the
s key (lower-case ’s’) to stage it. Once we do that, we can see that this file has now been added to the “Staged Changes” section which means it’s ready to be committed. At this point we could add more files to be committed if wanted to, but we’ll just go with this one for now.
We can now create a commit in our repository by pressing
c (lower-case ’c’) raise the “Commit” panel and then
c one more time to choose the “Commit” action.
Two panes appear, but we’re only going to focus on one of them right now: the commit message editor. In this pane, we can write a quick message about the changes that we’re commiting in this box. You can write as many lines as you like before the commentd lines with
# (hash) characters and they will all be included in the commit.
Once you’re finished writing your commit message, press
C-c C-c and the commit will be created!
In the next video I’ll go more in depth on the workflow for using Magit for everyday source control tasks like creating branches, making commits, and pushing those commits to a remote repository. We’ll also learn how to extend and amend our commits to fix them if we made mistakes or forgot to include changes.