In a recent answer in which he details the typical use cases of git-reset
\'s three most commonly used options (--hard
, --mixed
, and
I agree that at a first look those flags seem to be exotic. It took me hours to understand them, however the difference is pretty clear: --keep
unstages the index while --merge
completely discards the index.
Going back to a typical use cases: Imagine that you have a configuration file specific to your local environement, e.g., containing credentials to your local database. When you are going to do a "hard" reset, then for sure you don't want to loose your local changes. In that case
git reset --keep <commit>
perfectly does the job. This shows that more often you want to use --keep
flag instead of --hard
flag.
The flag --merge
is a bit more aggressive than --keep
since it completely discardes the index (notice that in this case you can lose your work in opposite to --keep
), but in my opinion the practical use cases for both of them are the same.
Originally, git reset --merge
was introduced to abort a merge, but now git merge --abort
is prefered (the first option was introduced in 1.6.2
version while the second one in 1.7.4
).
Frankly I'm not really sure about this; I've never even used the --merge
and --keep
modes myself. However, the release notes indicate that git reset --merge
was added in git version 1.6.2, with the following note:
git reset --merge
is a new mode that works similar to the way
git checkout
switches branches, taking the local changes while
switching to another commit.and --keep
was added in 1.7.1:
git reset
learned --keep
option that lets you discard commits
near the tip while preserving your local changes in a way similar
to how git checkout branch
does.Then, in 1.7.9:
git checkout -B <current branch> <elsewhere>
is a more intuitive
way to spell git reset --keep <elsewhere>
.which tells us that the idea behind --keep
is, you have started work on some branch, and then you realize: oh, this branch should fork off from some other point (probably the tip of some other branch). For instance you might:
$ git checkout devel
$ git checkout -b fix-bug-1234
and then do some work to fix bug 1234 for the next release; but then someone says: "hey, we need bug 1234 fixed for the old release version!" So now you want fix-bug-1234
to branch off from release
instead of devel
. Meanwhile you haven't committed anything yet. So you:
$ git checkout -B fix-bug-1234 release
to move it to "coming off release" instead of "coming off devel". Which works in 1.7.9 or later, but in 1.7.1 through 1.7.8 you have to spell it git reset --keep
.
That might explain --keep
but --merge
is still a bit of a mystery.