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.

4.2.1 Section Movement

To move within a section use the usual keys (C-p, C-n, C-b, C-f etc), whose global bindings are not shadowed. To move to another section use the following commands.

The section movement commands described here run the hook magit-section-movement-hook. Note that they explicitly run that hook and that arbitrary other movement, defined in Emacs and other packages, do not run that hook. That hook, and hook functions that can be added to it, or are part of its default value, are described below.

p (magit-section-backward)

When not at the beginning of a section, then move to the beginning of the current section. At the beginning of a section, instead move to the beginning of the previous visible section.

n (magit-section-forward)

Move to the beginning of the next visible section.

M-p (magit-section-backward-siblings)

Move to the beginning of the previous sibling section. If there is no previous sibling section, then move to the parent section instead.

M-n (magit-section-forward-siblings)

Move to the beginning of the next sibling section. If there is no next sibling section, then move to the parent section instead.

^ (magit-section-up)

Move to the beginning of the parent of the current section.

The above commands all call the hook magit-section-movement-hook. Any of the functions listed below can be used as members of this hook.

You might want to remove some of the functions that Magit adds using add-hook. In doing so you have to make sure you do not attempt to remove function that haven’t even been added yet, for example:

(with-eval-after-load 'magit-diff
  (remove-hook 'magit-section-movement-hook
               'magit-hunk-set-window-start))
Variable: magit-section-movement-hook

This hook is run by all of the above section movement commands, after arriving at the destination. It is not run by arbitrary other movement commands (such as next-line), which are provided by Emacs or third-party packages.

Function: magit-hunk-set-window-start

This hook function ensures that the beginning of the current section is visible, provided it is a hunk section. Otherwise, it does nothing.

Loading magit-diff adds this function to the hook.

Function: magit-section-set-window-start

This hook function ensures that the beginning of the current section is visible, regardless of the section’s type. If you add this to magit-section-movement-hook, then you must remove the hunk-only variant in turn.

Function: magit-log-maybe-show-more-commits

This hook function only has an effect in log buffers, and point is on the "show more" section. If that is the case, then it doubles the number of commits that are being shown.

Loading magit-log adds this function to the hook.

Function: magit-log-maybe-update-revision-buffer

When moving inside a log buffer, then this function updates the revision buffer, provided it is already being displayed in another window of the same frame.

Loading magit-log adds this function to the hook.

Function: magit-log-maybe-update-blob-buffer

When moving inside a log buffer and another window of the same frame displays a blob buffer, then this function instead displays the blob buffer for the commit at point in that window.

Function: magit-status-maybe-update-revision-buffer

When moving inside a status buffer, then this function updates the revision buffer, provided it is already being displayed in another window of the same frame.

Function: magit-status-maybe-update-stash-buffer

When moving inside a status buffer, then this function updates the stash buffer, provided it is already being displayed in another window of the same frame.

Function: magit-status-maybe-update-blob-buffer

When moving inside a status buffer and another window of the same frame displays a blob buffer, then this function instead displays the blob buffer for the commit at point in that window.

Function: magit-stashes-maybe-update-stash-buffer

When moving inside a buffer listing stashes, then this function updates the stash buffer, provided it is already being displayed in another window of the same frame.

User Option: magit-update-other-window-delay

Delay before automatically updating the other window.

When moving around in certain buffers using Magit’s own section movement commands (but not other movement commands), then certain other buffers, which are being displayed in another window, may optionally be updated to display information about the section at point.

When holding down a key to move by more than just one section, then that would update that buffer for each section on the way. To prevent that, updating the revision buffer is delayed, and this option controls for how long. For optimal experience you might have to adjust this delay and/or the keyboard repeat rate and delay of your graphical environment or operating system.

4.2.2 Section Visibility

Magit provides many commands for changing the visibility of sections, but all you need to get started are the next two.

TAB (magit-section-toggle)

Toggle the visibility of the body of the current section.

C-c TAB (magit-section-cycle)
C-<tab> (magit-section-cycle)

Cycle the visibility of current section and its children.

If this command is invoked using C-<tab> and that is globally bound to tab-next, then this command pivots to behave like that command, and you must instead use C-c TAB to cycle section visibility.

If you would like to keep using C-<tab> to cycle section visibility but also want to use tab-bar-mode, then you have to prevent that mode from using this key and instead bind another key to tab-next. Because tab-bar-mode does not use a mode map but instead manipulates the global map, this involves advising tab-bar--define-keys.

M-<tab> (magit-section-cycle-diffs)

Cycle the visibility of diff-related sections in the current buffer.

S-<tab> (magit-section-cycle-global)

Cycle the visibility of all sections in the current buffer.

1 (magit-section-show-level-1)
2 (magit-section-show-level-2)
3 (magit-section-show-level-3)
4 (magit-section-show-level-4)

Show sections surrounding the current section up to level N.

M-1 (magit-section-show-level-1-all)
M-2 (magit-section-show-level-2-all)
M-3 (magit-section-show-level-3-all)
M-4 (magit-section-show-level-4-all)

Show all sections up to level N.

Some functions, which are used to implement the above commands, are also exposed as commands themselves. By default no keys are bound to these commands, as they are generally perceived to be much less useful. But your mileage may vary.

Command: magit-section-show

Show the body of the current section.

Command: magit-section-hide

Hide the body of the current section.

Command: magit-section-show-headings

Recursively show headings of children of the current section. Only show the headings. Previously shown text-only bodies are hidden.

Command: magit-section-show-children

Recursively show the bodies of children of the current section. With a prefix argument show children down to the level of the current section, and hide deeper children.

Command: magit-section-hide-children

Recursively hide the bodies of children of the current section.

Command: magit-section-toggle-children

Toggle visibility of bodies of children of the current section.

When a buffer is first created then some sections are shown expanded while others are not. This is hard coded. When a buffer is refreshed then the previous visibility is preserved. The initial visibility of certain sections can also be overwritten using the hook magit-section-set-visibility-hook.

User Option: magit-section-initial-visibility-alist

This options can be used to override the initial visibility of sections. In the future it will also be used to define the defaults, but currently a section’s default is still hardcoded.

The value is an alist. Each element maps a section type or lineage to the initial visibility state for such sections. The state has to be one of show or hide, or a function that returns one of these symbols. A function is called with the section as the only argument.

Use the command magit-describe-section-briefly to determine a section’s lineage or type. The vector in the output is the section lineage and the type is the first element of that vector. Wildcards can be used, see magit-section-match.

User Option: magit-section-cache-visibility

This option controls for which sections the previous visibility state should be restored if a section disappears and later appears again. The value is a boolean or a list of section types. If t, then the visibility of all sections is cached. Otherwise this is only done for sections whose type matches one of the listed types.

This requires that the function magit-section-cached-visibility is a member of magit-section-set-visibility-hook.

Variable: magit-section-set-visibility-hook

This hook is run when first creating a buffer and also when refreshing an existing buffer, and is used to determine the visibility of the section currently being inserted.

Each function is called with one argument, the section being inserted. It should return hide or show, or to leave the visibility undefined nil. If no function decides on the visibility and the buffer is being refreshed, then the visibility is preserved; or if the buffer is being created, then the hard coded default is used.

Usually this should only be used to set the initial visibility but not during refreshes. If magit-insert-section--oldroot is non-nil, then the buffer is being refreshed and these functions should immediately return nil.

User Option: magit-section-visibility-indicators

This option controls whether and how to indicate that a section can be expanded/collapsed.

If nil, then don’t show any indicators. Otherwise the value has to be a list with two elements. The first controls the indicators used in graphical frames, the second the indicators in terminal frames. For graphical frames all of the following forms are valid, while terminal frames do not have fringes and thus do not support the first form.

  • (EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP)

    Both values have to be variables whose values are fringe bitmaps. In this case every section that can be expanded or collapsed gets an indicator in the left fringe.

    To provide extra padding around the indicator, set left-fringe-width in magit-mode-hook, e.g.:

    (add-hook 'magit-mode-hook
              (lambda () (setq left-fringe-width 20)))
    
  • (EXPANDABLE-CHAR . COLLAPSIBLE-CHAR)

    In this case every section that can be expanded or collapsed gets an indicator in the left margin.

  • (STRING . BOOLEAN)

    In this case STRING (usually an ellipsis) is shown at the end of the heading of every collapsed section. Expanded sections get no indicator. The cdr controls whether the appearance of these ellipsis take section highlighting into account. Doing so might potentially have an impact on performance, while not doing so is kinda ugly.

4.2.3 Section Hooks

Which sections are inserted into certain buffers is controlled with hooks. This includes the status and the refs buffers. For other buffers, e.g., log and diff buffers, this is not possible. The command magit-describe-section can be used to see which hook (if any) was responsible for inserting the section at point.

For buffers whose sections can be customized by the user, a hook variable called magit-TYPE-sections-hook exists. This hook should be changed using magit-add-section-hook. Avoid using add-hooks or the Custom interface.

The various available section hook variables are described later in this manual along with the appropriate "section inserter functions".

Function: magit-add-section-hook hook function &optional at append local

Add the function FUNCTION to the value of section hook HOOK.

Add FUNCTION at the beginning of the hook list unless optional APPEND is non-nil, in which case FUNCTION is added at the end. If FUNCTION already is a member then move it to the new location.

If optional AT is non-nil and a member of the hook list, then add FUNCTION next to that instead. Add before or after AT, or replace AT with FUNCTION depending on APPEND. If APPEND is the symbol replace, then replace AT with FUNCTION. For any other non-nil value place FUNCTION right after AT. If nil, then place FUNCTION right before AT. If FUNCTION already is a member of the list but AT is not, then leave FUNCTION where ever it already is.

If optional LOCAL is non-nil, then modify the hook’s buffer-local value rather than its global value. This makes the hook local by copying the default value. That copy is then modified.

HOOK should be a symbol. If HOOK is void, it is first set to nil. HOOK’s value must not be a single hook function. FUNCTION should be a function that takes no arguments and inserts one or multiple sections at point, moving point forward. FUNCTION may choose not to insert its section(s), when doing so would not make sense. It should not be abused for other side-effects.

To remove a function from a section hook, use remove-hook.

4.2.4 Section Types and Values

Each section has a type, for example hunk, file, and commit. Instances of certain section types also have a value. The value of a section of type file, for example, is a file name.

Users usually do not have to worry about a section’s type and value, but knowing them can be handy at times.

H (magit-describe-section)

This command shows information about the section at point in a separate buffer.

Command: magit-describe-section-briefly

This command shows information about the section at point in the echo area, as #<magit-section VALUE [TYPE PARENT-TYPE...] BEGINNING-END>.

Many commands behave differently depending on the type of the section at point and/or somehow consume the value of that section. But that is only one of the reasons why the same key may do something different, depending on what section is current.

Additionally for each section type a keymap might be defined, named magit-TYPE-section-map. That keymap is used as text property keymap of all text belonging to any section of the respective type. If such a map does not exist for a certain type, then you can define it yourself, and it will automatically be used.

4.2.5 Section Options

This section describes options that have an effect on more than just a certain type of sections. As you can see there are not many of those.

User Option: magit-section-show-child-count

Whether to append the number of children to section headings. This only affects sections that could benefit from this information.