git-reset hash sets the branch link to the given hash and, if necessary, checks it with --hard .
git-checkout hash sets the working tree to the specified hash; and if the hash is not the name of the branch, you will get a separate head.
ultimately, git deals with 3 things:
working tree (your code) ------------------------------------------------------------------------- index/staging-area ------------------------------------------------------------------------- repository (bunch of commits, trees, branch names, etc)
git-checkout by default simply updates the index and working tree and can optionally update something in the repository (with the -b option)
git-reset by default simply updates the repository and index, as well as possibly the working tree (with the --hard option)
You can think of a repository as follows:
HEAD -> master refs: master -> sha_of_commit_X dev -> sha_of_commit_Y objects: (addressed by sha1) sha_of_commit_X, sha_of_commit_Y, sha_of_commit_Z, sha_of_commit_A ....
git-reset handles what the branch reference points to.
Suppose your story looks like this:
T--S--R--Q [master][dev] / A--B--C--D--E--F--G [topic1] \ Z--Y--X--W [topic2][topic3]
Keep in mind that branches are simply names that are automatically committed when committed.
So, you have the following branches:
master -> Q dev -> Q topic1 -> G topic2 -> W topic3 -> W
And your current branch is topic2 , i.e. HEAD points to topic2.
HEAD -> topic2
Then git reset X will reset the topic2 name to point to X; this means that if you make a P commit in topic2, everything will look like this:
T--S--R--Q [master][dev] / A--B--C--D--E--F--G [topic1] \ Z--Y--X--W [topic3] \ P [topic2]