Staging changes

Choosing which of your changes the next commit will contain.

A commit does not have to contain everything you have done. Staging is how you choose: the staged changes are the next commit, and everything else waits.

That separation is worth using rather than working around. A morning’s work is rarely one change, and three commits that each do one thing are three commits you can read, revert or cherry-pick later — where one commit that does all three is a wall.

The mark at the end of the row

Every row with something to stage carries a mark at its right-hand end, saying how much of that file is in the next commit already: a hollow circle for Unstaged, a half-filled one for Partially staged, a filled tick for Staged. Point at the row and the same mark becomes the action it offers — a green plus to stage, an amber minus to unstage — and pressing it acts on that file and nothing else. It does not select the row, reload the diff, or open or close a folder.

The mark keeps its place whether it is reporting or offering, so the column stays still as you go down the list, and it belongs to the keyboard as much as to the pointer: give it the focus and it offers the same action. A file that is partly staged offers Stage remaining changes, since that is what is left to do to it; taking the whole file back out is ⌥⌘U, or Unstage in its context menu.

By file

Select a file and press ⌥⌘A. Select several — click, then shift-click or command-click — and the same command stages all of them.

Staging an untracked file makes it an addition: the mark on Scanner.swift changes from a question mark to an A, and the mark at the other end of the row becomes a tick.

There is no staged group to move into. What changes is the mark at the end of the row, and the count above the commit message that the Commit button waits on. An untracked file changes its other mark as well — Untracked becomes Added — because Git has now recorded it.

Repository ▸ Stage All (⇧⌘A) takes the lot. Repository ▸ Unstage All (⇧⌘U) and ⌥⌘U are the exact opposites, and neither touches the file on disk — unstaging only changes what the next commit will contain.

By folder

In the folder hierarchy, which is how the list starts until you choose View ▸ Working Copy Files ▸ Grouped by Status, a folder row stages, unstages or discards everything under it in one action, and shows how many files that is before you do.

Its mark aggregates what is below it: Staged only when everything under it is, Unstaged when none of it is, Partially staged for every mixture. In the figure above both files under Sources / Kettle are staged, so the folder’s mark is a tick too, and README.md, outside it, keeps its own. The action follows — while anything below is unstaged the folder stages that part, and only a folder that is staged throughout offers to unstage it — so what the row is about to do is never ambiguous.

The row also shows which files its action would reach. Point at the folder’s own mark, or give it the keyboard focus, and each of those rows takes the same plus or minus, drawn faintly; a closed subfolder takes it too if there is a file inside it. Nothing else moves — no row is selected, no folder opens — and it clears when you look away.

Finer than a file

You do not have to take a whole file. The diff gutter stages one hunk, or one line, or a block of lines dragged across the gutter — see staging hunks and single lines.

Everything is reachable without the mouse

Every staging action has a keyboard equivalent, a context menu entry, and a VoiceOver route to the same thing. The commands are listed in the Repository menu with their key equivalents, and in the Command Palette (⌘K) if you would rather search for them by name.