A Git Porcelain inside Emacs
It’s Magit! A Git Porcelain inside Emacs
Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains. (less)
Staging and otherwise applying changes is one of the most important features in a Git porcelain and here Magit outshines anything else, including Git itself. Git’s own staging interface (git add --patch
) is so cumbersome that many users only use it in exceptional cases. In Magit staging a hunk or even just part of a hunk is as trivial as staging all changes made to a file.
The most visible part of Magit’s interface is the status buffer, which displays information about the current repository. Its content is created by running several Git commands and making their output actionable. Among other things, it displays information about the current branch, lists unpulled and unpushed changes and contains sections displaying the staged and unstaged changes. That might sound noisy, but, since sections are collapsible, it’s not.
To stage or unstage a change one places the cursor on the change and then types s
or u
. The change can be a file or a hunk, or when the region is active (i.e. when there is a selection) several files or hunks, or even just part of a hunk. The change or changes that these commands - and many others - would act on are highlighted.
Magit also implements several other “apply variants” in addition to staging and unstaging. One can discard or reverse a change, or apply it to the working tree. Git’s own porcelain only supports this for staging and unstaging and you would have to do something like git diff ... | ??? | git apply ...
to discard, revert, or apply a single hunk on the command line. In fact that’s exactly what Magit does internally (which is what lead to the term “apply variants”).
Magit isn’t just for Git experts, but it does assume some prior experience with Git as well as Emacs. That being said, many users have reported that using Magit was what finally taught them what Git it is capable off and how to use it to its fullest. Other users wished they had switched to Emacs sooner so that they would have gotten their hands on Magit earlier.
While one has to know the basic features of Emacs to be able to make full use of Magit, acquiring just enough Emacs skills doesn’t take long and is worth it, even for users who prefer other editors. Vim users are advised to give Evil the “Extensible VI Layer for Emacs”, and Spacemacs an “Emacs starter-kit focused on Evil” a try.
Magit provides a consistent and efficient Git porcelain. After a short learning period, you will be able to perform most of your daily version control tasks faster than you would on the command line. You will likely also start using features that seemed too daunting in the past.
Magit fully embraces Git. It exposes many advanced features using a simple but flexible interface instead of only wrapping the trivial ones like many GUI clients do. Of course Magit supports logging, cloning, pushing, and other commands that usually don’t fail in spectacular ways; but it also supports tasks that often cannot be completed in a single step. Magit fully supports tasks such as merging, rebasing, cherry-picking, reverting, and blaming by not only providing a command to initiate these tasks but also by displaying context sensitive information along the way and providing commands that are useful for resolving conflicts and resuming the sequence after doing so.
Magit wraps and in many cases improves upon at least the following Git porcelain commands: add, am, bisect, blame, branch, checkout, cherry, cherry-pick, clean, clone, commit, config, describe, diff, fetch, format-patch, init, log, merge, merge-tree, mv, notes, pull, rebase, reflog, remote, request-pull, reset, revert, rm, show, stash, submodule, and tag. Many more Magit porcelain commands are implemented on top of Git plumbing commands.
两点:staging and status buffer.
Introduction: | |
---|---|
• Installation: | |
• Getting Started: | |
• Interface Concepts: | |
• Inspecting: | |
• Manipulating: | |
• Transferring: | |
• Miscellaneous: | |
• Customizing: | |
• Plumbing: | |
• FAQ: | |
• Debugging Tools: | |
• Keystroke Index: | |
• Command Index: | |
• Function Index: | |
• Variable Index: |
3 Getting Started
This short tutorial describes the most essential features that many Magitians use on a daily basis. It only scratches the surface but should be enough to get you started.
IMPORTANT: It is safest if you clone some repository just for this tutorial. Alternatively you can use an existing local repository, but if you do that, then you should commit all uncommitted changes before proceeding.
To display information about the current Git repository, type M-x magit-status RET
. You will be using this command a lot, and should therefore give it a global key binding. This is what we recommend:
1 | (global-set-key (kbd "C-x g") 'magit-status) |
Most Magit commands are commonly invoked from the status buffer. It can be considered the primary interface for interacting with Git using Magit. Many other Magit buffers may exist at a given time, but they are often created from this buffer.
Depending on what state your repository is in, this buffer may contain sections titled “Staged changes”, “Unstaged changes”, “Unmerged into origin/master”, “Unpushed to origin/master”, and many others.
Since we are starting from a safe state, which you can easily return to (by doing a git reset --hard PRE-MAGIT-STATE
), there currently are not staged or unstaged changes. Edit some files and save the changes. Then go back to the status buffer, while at the same time refreshing it, by typing C-x g
. (When the status buffer, or any Magit buffer for that matter, is the current buffer, then you can also use just g
to refresh it).
Move between sections using p
and n
. Note that the bodies of some sections are hidden. Type TAB
to expand or collapse the section at point. You can also use C-tab
to cycle the visibility of the current section and its children. Move to a file section inside the section named “Unstaged changes” and type s
to stage the changes you have made to that file. That file now appears under “Staged changes”.
Magit can stage and unstage individual hunks, not just complete files. Move to the file you have just staged, expand it using TAB
, move to one of the hunks using n
, and unstage just that by typing u
. Note how the staging (s
) and unstaging (u
) commands operate on the change at point. Many other commands behave the same way.
You can also un-/stage just part of a hunk. Inside the body of a hunk section (move there using C-n
), set the mark using C-SPC
and move down until some added and/or removed lines fall inside the region but not all of them. Again type s
to stage.
It is also possible to un-/stage multiple files at once. Move to a file section, type C-SPC
, move to the next file using n
, and then s
to stage both files. Note that both the mark and point have to be on the headings of sibling sections for this to work. If the region looks like it does in other buffers, then it doesn’t select Magit sections that can be acted on as a unit.
And then of course you want to commit your changes. Type c
. This shows the available commit commands and arguments in a buffer at the bottom of the frame. Each command and argument is prefixed with the key that invokes/sets it. Do not worry about this for now. We want to create a “normal” commit, which is done by typing c
again.
Now two new buffers appear. One is for writing the commit message, the other shows a diff with the changes that you are about to committed. Write a message and then type C-c C-c
to actually create the commit.
You probably don’t want to push the commit you just created because you just committed some random changes, but if that is not the case you could push it by typing P
to show all the available push commands and arguments and then p
to push to a branch with the same name as the local branch onto the remote configured as the push-remote. (If the push-remote is not configured yet, then you would first be prompted for the remote to push to.)
So far we have mentioned the commit, push, and log transient prefix commands. These are probably among the transients you will be using the most, but many others exist. To show a transient that lists all other transients (as well as the various apply commands and some other essential commands), type h
. Try a few.
The key bindings in that transient correspond to the bindings in Magit buffers, including but not limited to the status buffer. So you could type h d
to bring up the diff transient, but once you remember that “d” stands for “diff”, you would usually do so by just typing d
. But this “prefix of prefixes” is useful even once you have memorized all the bindings, as it can provide easy access to Magit commands from non-Magit buffers. You should create a global key binding for this command too:
1 | (global-set-key (kbd "C-x M-g") 'magit-dispatch) |
In the same vein, you might also want to enable global-magit-file-mode
to get some more Magit key bindings in regular file-visiting buffers (see Minor Mode for Buffers Visiting Files).
It is not necessary that you do so now, but if you stick with Magit, then it is highly recommended that you read the next section too.
Next: Interface Concepts, Previous: Installation, Up: Top [Contents][Index]
4 Interface Concepts
• Modes and Buffers: | ||
---|---|---|
• Sections: | ||
• Transient Commands: | ||
• Completion, Confirmation and the Selection: | ||
• Running Git: |
4.1 Modes and Buffers
Magit provides several major-modes. For each of these modes there usually exists only one buffer per repository. Separate modes and thus buffers exist for commits, diffs, logs, and some other things.
Besides these special purpose buffers, there also exists an overview buffer, called the status buffer. It’s usually from this buffer that the user invokes Git commands, or creates or visits other buffers.
In this manual we often speak about “Magit buffers”. By that we mean buffers whose major-modes derive from magit-mode
.
M-x magit-toggle-buffer-lock (
magit-toggle-buffer-lock
)This command locks the current buffer to its value or if the buffer is already locked, then it unlocks it.Locking a buffer to its value prevents it from being reused to display another value. The name of a locked buffer contains its value, which allows telling it apart from other locked buffers and the unlocked buffer.Not all Magit buffers can be locked to their values; for example, it wouldn’t make sense to lock a status buffer.There can only be a single unlocked buffer using a certain major-mode per repository. So when a buffer is being unlocked and another unlocked buffer already exists for that mode and repository, then the former buffer is instead deleted and the latter is displayed in its place.
• Switching Buffers: | ||
---|---|---|
• Naming Buffers: | ||
• Quitting Windows: | ||
• Automatic Refreshing of Magit Buffers: | ||
• Automatic Saving of File-Visiting Buffers: | ||
• Automatic Reverting of File-Visiting Buffers: |
4.2 Sections
Magit buffers are organized into nested sections, which can be collapsed and expanded, similar to how sections are handled in Org mode. Each section also has a type, and some sections also have a value. For each section type there can also be a local keymap, shared by all sections of that type.
Taking advantage of the section value and type, many commands operate on the current section, or when the region is active and selects sections of the same type, all of the selected sections. Commands that only make sense for a particular section type (as opposed to just behaving differently depending on the type) are usually bound in section type keymaps.
• Section Movement: | ||
---|---|---|
• Section Visibility: | ||
• Section Hooks: | ||
• Section Types and Values: | ||
• Section Options: |
4.3 Transient Commands
Many Magit commands are implemented as transient commands. First the user invokes a prefix command, which causes its infix arguments and suffix commands to be displayed in the echo area. The user then optionally sets some infix arguments and finally invokes one of the suffix commands.
This is implemented in the library transient
. Earlier Magit releases used the package magit-popup
and even earlier versions library magit-key-mode
.
Transient is documented in (transient)Top.
C-c C-c (
magit-dispatch
)This transient prefix command binds most of Magit’s other prefix commands as suffix commands and displays them in a temporary buffer until one of them is invoked. Invoking such a sub-prefix causes the suffixes of that command to be bound and displayed instead of those of
magit-dispatch
.
This command is also, or especially, useful outside Magit buffers, so you should setup a global binding:
1 | (global-set-key (kbd "C-x M-g") 'magit-dispatch) |
Transient commands remember the used arguments for subsequent invocations. Two transients, the log and diff transients (see Logging and Diffing), may behave a bit differently, depending on the value of magit-use-sticky-arguments
.
User Option: magit-use-sticky-arguments
This option controls how the diff and log transients reuse arguments from existing buffers.When
t
(the default value), then the log or diff transients reuses the arguments from the current repository’s log or diff buffer, respectively. When no log or diff buffer exists for the current repository, these transients use the default value ofmagit-log-arguments
ormagit-diff-arguments
.Whencurrent
, log and diff transients will only reuse the arguments if the current buffer is derived frommagit-log-mode
ormagit-diff-mode
, respectively.Whennil
, the default value ofmagit-log-arguments
ormagit-diff-arguments
is always used.
4.4 Completion, Confirmation and the Selection
• Action Confirmation: | ||
---|---|---|
• Completion and Confirmation: | ||
• The Selection: | ||
• The hunk-internal region: | ||
• Support for Completion Frameworks: | ||
• Additional Completion Options: |
4.5 Running Git
• Viewing Git Output: | ||
---|---|---|
• Git Process Status: | ||
• Running Git Manually: | ||
• Git Executable: | ||
• Global Git Arguments: |
4.5.1 Viewing Git Output
Magit runs Git either for side-effects (e.g. when pushing) or to get some value (e.g. the name of the current branch).
When Git is run for side-effects, the process output is logged in a per-repository log buffer, which can be consulted using the magit-process
command when things don’t go as expected.
The output/errors for up to ‘magit-process-log-max’ Git commands are retained.
$ (
magit-process
)This commands displays the process buffer for the current repository.
Inside that buffer, the usual key bindings for navigating and showing sections are available. There is one additional command.
k (
magit-process-kill
)This command kills the process represented by the section at point.
User Option: magit-git-debug
When this is non-nil then the output of all calls to git are logged in the process buffer. This is useful when debugging, otherwise it just negatively affects performance.
5 Inspecting
The functionality provided by Magit can be roughly divided into three groups:
inspecting existing data,
manipulating existing data or adding new data,
transferring data. (划分的好.)
Of course that is a rather crude distinction that often falls short, but it’s more useful than no distinction at all. This section is concerned with inspecting data, the next two with manipulating and transferring it. Then follows a section about miscellaneous functionality, which cannot easily be fit into this distinction.
Of course other distinctions make sense too, e.g. Git’s distinction between porcelain and plumbing commands, which for the most part is equivalent to Emacs’ distinction between interactive commands and non-interactive functions. All of the sections mentioned before are mainly concerned with the porcelain – Magit’s plumbing layer is described later.
• Status Buffer: | ||
---|---|---|
• Repository List: | ||
• Logging: | ||
• Diffing: | ||
• Ediffing: | ||
• References Buffer: | ||
• Bisecting: | ||
• Visiting Blobs: | ||
• Blaming: |
5.1 Status Buffer
While other Magit buffers contain e.g. one particular diff or one particular log, the status buffer contains the diffs for staged and unstaged changes, logs for unpushed and unpulled commits, lists of stashes and untracked files, and information related to the current branch.
During certain incomplete operations – for example when a merge resulted in a conflict – additional information is displayed that helps proceeding with or aborting the operation.
The command magit-status
displays the status buffer belonging to the current repository in another window. This command is used so often that it should be bound globally. We recommend using C-x g
:
1 | (global-set-key (kbd "C-x g") 'magit-status) |
C-x g (
magit-status
)When invoked from within an existing Git repository, then this command shows the status of that repository in a buffer.If the current directory isn’t located within a Git repository, then this command prompts for an existing repository or an arbitrary directory, depending on the option
magit-repository-directories
, and the status for the selected repository is shown instead.If that option specifies any existing repositories, then the user is asked to select one of them.Otherwise the user is asked to select an arbitrary directory using regular file-name completion. If the selected directory is the top-level directory of an existing working tree, then the status buffer for that is shown.Otherwise the user is offered to initialize the selected directory as a new repository. After creating the repository its status buffer is shown.These fallback behaviors can also be forced using one or more prefix arguments:With two prefix arguments (or more precisely a numeric prefix value of 16 or greater) an arbitrary directory is read, which is then acted on as described above. The same could be accomplished using the commandmagit-init
.With a single prefix argument an existing repository is read from the user, or if no repository can be found based on the value ofmagit-repository-directories
, then the behavior is the same as with two prefix arguments.User Option: magit-repository-directories
List of directories that are Git repositories or contain Git repositories.Each element has the form
(DIRECTORY . DEPTH)
. DIRECTORY has to be a directory or a directory file-name, a string. DEPTH, an integer, specifies the maximum depth to look for Git repositories. If it is 0, then only add DIRECTORY itself.This option controls which repositories are being listed bymagit-list-repositories
. It also affectsmagit-status
(which see) in potentially surprising ways (see above).Command: ido-enter-magit-status
From an Ido prompt used to open a file, instead drop into
magit-status
. This is similar toido-magic-delete-char
, which, despite its name, usually causes a Dired buffer to be created.To make this command available, use something like:(add-hook 'ido-setup-hook (lambda () (define-key ido-completion-map (kbd \"C-x g\") 'ido-enter-magit-status)))
Starting with Emacs 25.1 the Ido keymaps are defined just once instead of every time Ido is invoked, so now you can modify it like pretty much every other keymap:(define-key ido-common-completion-map (kbd \"C-x g\") 'ido-enter-magit-status)
• Status Sections: | ||
---|---|---|
• Status Header Sections: | ||
• Status Module Sections: | ||
• Status Options: |
6 Manipulating
• Repository Setup: | ||
---|---|---|
• Staging and Unstaging: | ||
• Applying: | ||
• Committing: | ||
• Branching: | ||
• Merging: | ||
• Resolving Conflicts: | ||
• Rebasing: | ||
• Cherry Picking: | ||
• Resetting: | ||
• Stashing: |
7 Transferring
• Remotes: | ||
---|---|---|
• Fetching: | ||
• Pulling: | ||
• Pushing: | ||
• Plain Patches: | ||
• Maildir Patches: |
8 Miscellaneous
• Tagging: | ||
---|---|---|
• Notes: | ||
• Submodules: | ||
• Subtree: | ||
• Worktree: | ||
• Common Commands: | ||
• Wip Modes: | ||
• Minor Mode for Buffers Visiting Files: | ||
• Minor Mode for Buffers Visiting Blobs: |
9 Customizing
Both Git and Emacs are highly customizable. Magit is both a Git porcelain as well as an Emacs package, so it makes sense to customize it using both Git variables as well as Emacs options. However this flexibility doesn’t come without problems, including but not limited to the following.
Some Git variables automatically have an effect in Magit without requiring any explicit support. Sometimes that is desirable - in other cases, it breaks Magit.
When a certain Git setting breaks Magit but you want to keep using that setting on the command line, then that can be accomplished by overriding the value for Magit only by appending something like
("-c" "some.variable=compatible-value")
tomagit-git-global-arguments
.Certain settings like
fetch.prune=true
are respected by Magit commands (because they simply call the respective Git command) but their value is not reflected in the respective transient buffers. In this case the--prune
argument inmagit-fetch
might be active or inactive, but that doesn’t keep the Git variable from being honored by the suffix commands anyway. So pruning might happen despite the--prune
arguments being displayed in a way that seems to indicate that no pruning will happen.
I intend to address these and similar issues in a future release.
• Per-Repository Configuration: | ||
---|---|---|
• Essential Settings: |
10 Plumbing
The following sections describe how to use several of Magit’s core abstractions to extend Magit itself or implement a separate extension.
A few of the low-level features used by Magit have been factored out into separate libraries/packages, so that they can be used by other packages, without having to depend on Magit. See (with-editor)Top for information about with-editor
. transient
doesn’t have a manual yet.
If you are trying to find an unused key that you can bind to a command provided by your own Magit extension, then checkout https://github.com/magit/magit/wiki/Plugin-Dispatch-Key-Registry.
• Calling Git: | ||
---|---|---|
• Section Plumbing: | ||
• Refreshing Buffers: | ||
• Conventions: |
Appendix A FAQ
The next two nodes lists frequently asked questions. For a list of frequently and recentlyasked questions, i.e. questions that haven’t made it into the manual yet, seehttps://github.com/magit/magit/wiki/FAQ.
Please also use the Debugging Tools.
• FAQ - How to …?: | ||
---|---|---|
• FAQ - Issues and Errors: |