Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is the difference between all the Git Reset modes?

Tags:

git

git-reset

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?

like image 639
Steve Bennett Avatar asked Dec 08 '22 00:12

Steve Bennett


1 Answers

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..."

  • "HEAD": what HEAD points to after the operation
  • "Branch pointer": if we are currently on the tip of a branch B, what B points to afterwards
  • "Empty index": what you'll see happen when doing a reset with no staged changes.
  • "Tracked files": whether files in the working directory will be changed if switching to a commit that affects them
  • "Untracked files": whether untracked files in the working directory will be changed. (Spoiler: No)

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

*Note on --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.

Summary

The different git reset modes are defined by these questions:

  • are staged changes retained (soft), unstaged (mixed, keep) or discarded (merge, hard)
  • is the working directory updated always (hard), only if safe (keep, merge) or never (soft, mixed)
  • are unrelated unstaged changes retained (soft, mixed, merge, keep) or discarded (hard)

My final succinct descriptions of each:

  • mixed (default): unstage staged, keep unstaged, don't touch working (safe)
  • soft: just move HEAD, stage differences (safe)
  • hard: discard staged, discard unstaged, update working (unsafe)
  • merge: discard staged, keep unstaged, update working (abort if unsafe)
  • keep: unstage staged, keep unstaged, update working (abort if unsafe)
like image 199
Steve Bennett Avatar answered Dec 11 '22 07:12

Steve Bennett