Reputation: 126005
I'm trying to add succinct summaries of Git's reset modes for the Git-Savvy Sublime extension. It's hard!
I have this:
mixed (default): update index
soft: move branch pointer only
hard: update index & working dir, discard local changes
merge: update index & working dir, keep local changes
keep: update index & working dir, abort if local changes
(Hopefully it's implied that the branch pointer moves in all modes.)
The documentation around the reset
modes is pretty murky, and uses the phrases "updates the index", "touches the index file", "resets the index" and "resets index entries" with no way of knowing whether they're synonymous or not.
Are there other subtle differences between --hard
, --merge
and --keep
?
Upvotes: 7
Views: 3050
Reputation: 126005
Ok, since I can't find a complete side-by-side analysis of the different modes, I'll make a table, using language which is hopefully more understandable to the user. I'm also including git checkout
.
For clarity, the "Effect on..."
Clean working directory:
Effect on | soft | mixed | hard | merge | keep |checkout
-----------------+---------------------------------------------|--------
HEAD | Move | Move | Move | Move | Move | Move
Branch pointer | Move | Move | Move | Move | Move | -
Empty index | Add* | - | - | - | - | -
Tracked files | - | - | Change | Change | Change |Change
Untracked files | - | - | - | - | - | -
Changes in working directory (possibly staged) that aren't affected by the commit we're resetting/checking out. (eg, we change file.txt, but there's no change in it between the current commit and where we're going)
(-
means "keep in current state", Both
means staged and unstaged changes to the same file)
Staged changes | - | Unstage | Discard | Discard | Unstage| -
Unstaged changes | - | - | Discard | - | - | -
Both | - * | Unstage | Discard | Abort | Unstage| -
Changes in working directory (possibly staged) that are affected by the commit we're resetting/checking out. Sometimes expressed as asking if the operation is "working directory safe".
Effect on | soft | mixed | hard | merge | keep |checkout
-----------------+---------------------------------------------|--------
Staged changes | - | Unstage | Discard | Discard | Abort | Abort
Unstaged changes | - * | - | Discard | Abort | Abort | Abort
Both | - * | Unstage | Discard | Abort | Abort | Abort
--soft
git reset --soft X
turns changes between working directory (including current HEAD) and X into staged changes. Git's man page counter-intuitively describes this as "not touching the index file".
When there are staged changes, --soft
combines them with new staged changes.
When there unstaged changes, --soft
keeps the unstaged changes, but also stages new changes as above. It's consistent but potentially confusing.
The different git reset
modes are defined by these questions:
soft
), unstaged (mixed
, keep
) or discarded (merge
, hard
)hard
), only if safe (keep
, merge
) or never (soft
, mixed
)soft
, mixed
, merge
, keep
) or discarded (hard
)My final succinct descriptions of each:
Upvotes: 18
Reputation: 1323115
First, git reset resets HEAD.
And HEAD is not always a "branch pointer": it is the current commit.
Second, a git reset
can reset at commit level or at file level (you can reset a file).
But in any cases, I would use the two words "moves HEAD".
You will find a more accurate table in git reset
Demystified:
head index work dir wd safe
Commit Level
reset --soft [commit] REF NO NO YES
reset [commit] REF YES NO YES
reset --hard [commit] REF YES YES NO
checkout [commit] HEAD YES YES YES
File Level
reset (commit) [file] NO YES NO YES
checkout (commit) [file]NO YES YES NO
See also:
git reset
vs git reset HEAD
" to understand why git reset defaults to HEAD
(while git checkout -- path
does not).git reset
” and “git checkout
”?"Upvotes: 1