I'm looking to split a commit up and not sure which reset option to use.
I was looking at the page In plain English, what does "git reset" do?, but I realized I don't really understand what the git index or staging area is and thus the explanations didn't help.
Also, the use cases for --mixed
and --soft
look the same to me in that answer (when you want to fix and recommit). Can someone break it down even more? I realize --mixed
is probably the option to go with, but I want to know why. Lastly, what about --hard
?
Can someone give me a workflow example of how selecting the 3 options would happen?
git reset --soft , which will keep your files, and stage all changes back automatically. git reset --hard , which will completely destroy any changes and remove them from the local directory. Only use this if you know what you're doing.
Reset the staging area and the working directory to match the most recent commit. In addition to unstaging changes, the --hard flag tells Git to overwrite all changes in the working directory, too.
First, it's always worth noting that git reset --hard is a potentially dangerous command, since it throws away all your uncommitted changes. For safety, you should always check that the output of git status is clean (that is, empty) before using it.
When using git reset --soft HEAD~1 you will remove the last commit from the current branch, but the file changes will stay in your working tree. Also the changes will stay on your index, so following with a git commit will create a commit with the exact same changes as the commit you "removed" before.
When you modify a file in your repository, the change is initially unstaged. In order to commit it, you must stage it—that is, add it to the index—using git add
. When you make a commit, the changes that are committed are those that have been added to the index.
git reset
changes, at minimum, where the current branch (HEAD
) is pointing. The difference between --mixed
and --soft
is whether or not your index is also modified. So, if we're on branch master
with this series of commits:
- A - B - C (master)
HEAD
points to C
and the index matches C
.
When we run git reset --soft B
, master
(and thus HEAD
) now points to B
, but the index still has the changes from C
; git status
will show them as staged. So if we run git commit
at this point, we'll get a new commit with the same changes as C
.
Okay, so starting from here again:
- A - B - C (master)
Now let's do git reset --mixed B
. (Note: --mixed
is the default option). Once again, master
and HEAD
point to B, but this time the index is also modified to match B
. If we run git commit
at this point, nothing will happen since the index matches HEAD
. We still have the changes in the working directory, but since they're not in the index, git status
shows them as unstaged. To commit them, you would git add
and then commit as usual.
And finally, --hard
is the same as --mixed
(it changes your HEAD
and index), except that --hard
also modifies your working directory. If we're at C
and run git reset --hard B
, then the changes added in C
, as well as any uncommitted changes you have, will be removed, and the files in your working copy will match commit B
. Since you can permanently lose changes this way, you should always run git status
before doing a hard reset to make sure your working directory is clean or that you're okay with losing your uncommitted changes.
And finally, a visualization:
In the simplest terms:
--soft
: uncommit changes, changes are left staged (index).--mixed
(default): uncommit + unstage changes, changes are left in working tree.--hard
: uncommit + unstage + delete changes, nothing left.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With