Both of these can be solved with "git reset".
Before going into any more detail on that, let's go over the other related "basic operations" too:
- "git branch". This creates a new branch of development at an arbitrary
point (that defaults to "current state").
Example:
git branch development-trial v1.1.6
This will create a new branch called "development-trial", which starts
at the v1.1.6 state. NOTE! It will _not_ check it out - your old active
state is left totally alone, and you still stay on whatever branch you
used to be on.
- "git checkout". This switches to another branch. As a shorthand, you
can also choose to create the branch at the same time, but normally
you'd just do like this example:
git checkout development-trial
which will switch to the branch you just created and check that out.
- "git reset". This will reset the current branch state to something
else. This is what you would use if you want to undo a commit,
for example: you can "reset" the current branch to before the commit
happened.
NOTE! When you do this, you also have to choose what you want to do
about your checked-out working tree. For example, when undoing the last
commit, you normally want to totally undo all the working tree changes
too, but you might also want to just undo the commit, and leave the
actual changes you committed alone, so that you can re-commit them with
a fixed commit message, for example.
Example:
git reset --hard HEAD^
this will undo the last commit (more exactly: it will select the first
parent of HEAD to be the new top-of-development, so if the last thing
you did was a merge, it will reset to the previous state). The "--hard"
means that you want to reset the working tree too.
Other example:
git reset --hard v1.1.6
This will just reset the current branch to a particular known state (ie
1.1.6 in this case).
Without the "--hard", it will _not_ change the working tree, but just
update the index (and branch pointer, of course) to the new state, and
tell you which files are "dirty" in that new state. This is great for
undoing just a "git commit", but leaving the tree in the state is was
before you committed. It's not so great if you expected to revert
everything, and are now confused because "git diff" shows lots of
changes ;)
Finally, let's go over the difference between "git fetch" and "git pull":
- "git fetch" is what you want to do if you want to _update_ another
branch. For example, if you want to track what Junio is doing in his
git repository (assuming that was what you cloned for), doing
git fetch origin
will update the "origin" branch, but will _not_ touch the current
branch itself. This is very useful for seeing what Junio has been
doing, without actually affecting your own work in any way.
- "git pull" is really just "git fetch" + "git merge". It will fetch the
state you asked for, and then merge that into your current branch. So
it's important to rmember that this actually _changes_ what you have
checked out and have worked on.
One very special case of "git pull" is when you only use the repository
to track another branch, and you never do any changes at all, and you
never switch branches around, and you always pull from the same source.
In that case, "git pull" will basically boil down to just a read-only
tracking mechanism (ie you could think of this particular usage as
being the git equivalent of "anoncvs" access)
The reason people may get confused is that they start out using "git pull" as a read-only tracking mechanism, and it's not necessarily obvious that "git pull" really fundamentally is a very powerful operations - much MUCH more complex and powerful than just "track that other branch". Which is why I try to make the distinction between "git fetch" and "git pull" clear.
Linus