Lets continue from p1. I promised interactive add, rebase and cherry-pick. Here they come!
interactive add
So here's the use case: you've been working as usual in your git repo, and suddenly a co-worker comes by tell you about this crazy bug. You start working on another thing, in the same branch, without stashing. Then the same happens again, now with a more severe bug. At the end you have a few separe changes going on in the same folder, touching the same files in different (or the same) locations.
Now you want, as a good code monkey, to commit each change in a separate commit. To do this you can use git add -p [filename]. That will prompt for each individual modified chunk, whether you want it added to the index. The cool thing is that you can split a long chunk in smaller ones (using s), or even edit the chunk with your favourite editorvim, for the most control.
rebase
I think rebase is the coolest feature of git. It just lets you modify your history in all ways imaginable, with a pretty neat interface :)
There are a few use cases. First imagine you've been working on some feature on a branch, where other also commit. Now that you have created a few commits and want to push you realize there are new commits on that branch, so you have to somehow combine your commits with the upstream commits. There are 2 options: merging and rebasing. Merging creates a new commit that combines you head with the remote head. It is the most straight forward, but it also complicates the history -- if you run git log --graph you'll see what I mean. If you prefer your history straight you have to use rebase. It moves your commits on top of the remote ones.
If you're contributing to open source project you might be required to rebase your commits on top of the latest HEAD. github pull requests are actually smart enough, so you can rebase and force-push and the rebased commits will appear in place of the old ones.
Another legitimate use case of rebase is to tidy up your commits before submitting them upstream. You can reorder commits, edit old commits, change their commit message and squash a few commits together. Just use the --interactive (or -i) switch -- you'll see all your commits in an editor, you can reorder them by copy-pasting lines, and other actions are achieved by changing the word in the begining of each line. The person who came up with this interface is genius.
The usage is simple (do you expect me to say anything else?): git rebase [on-top-of [what]]. If you're in the branch that you want to rewrite, you can just specify on-top-of, or where do you want to start placing the new (rewritten) commits. what is the branch you want to rebase, in case you're not on it right now. If you just want to rewrite some history, go to the head and say git rebase -i last-unchanged-commit to reorder, reword, squash the commits after last-unchanged-commit.
If you just want to rebase unpushed changes on top of current HEAD, you can use git pull -r -- that is pull and rebase, not merge.
When you hit a rebase issue, you git add the broken files after you've fixed them and you issue git rebase --continue. If shit hits the fan -- bail out with git rebase --abort.
cherry-pick
Cherry pick lets you copy one commit to another place (normally another branch). You just go where you want the commit to be copied, and say git cherry-pick commit-id. That is it. If you were looking for something more fancy -- sorry for the disappointment.
stash (bonus material)
Consider the use case in the interactive add scenario. Only this time you realize on time, that you'd start working on a second thing, so you can save your current changes for later. You just say git stash [-u] and you have a clean folder again, ready for hacking! -u tells stash to also save the untracked files -- really handy. When you're done hacking and want to continue your work you do git stash pop -- which brings back all the changes you'd done before the stash.