Here's my short-list cheat sheet I use for OSS development
Day-to-day commands
# Update the working copy from the trunk
git pull --rebase
If you aren't the project owner you will use this command more than anything. Basically, pull the latest changes and change to the current version all in one step.
# Goes back one commit in case something was forgotten
git reset --soft HEAD^
Unless you write perfect code with 0 conflicts (don't worry, you don't) you'll need to go back and resolve issues. This drops back one revision so you can add whatever you forgot.
# Reverts the working copy back to the trunk revision
git reset HEAD~
Resets the repository to the HEAD revision. If there are multiple users working on the same codebase, it saves a lot of headaches to save away your changes and pull the latest commit before committing. The key is to keep the tree as clean as possible to cut down on the amount of conflicts/issues/headaches.
# Gives a summary of a commit without executing it
git commit -a --dry-run
Doing a dry run on a commit will let you know where conflicts exist without actually committing the code. Resolving conflicts before the actual commit is easier than after.
Making sure your commits go in clean is essential to maintaining a clean revision tree. especially when there are multiple devs working on a project in parallel.
# Amend the log from the last commit
git commit --amend
Nothing special but extremely useful. It lets you edit the last commit. If you're working on a team project, making good notes about commits is essential. This saves from having to go through all the effort of a soft reset to make the change.
# Saves the uncommited changes
git stash save
# Shows a listing of the saved stashes
git stash list
# Applies the stash @ ID 0
git stash apply stash@{0}
# Removes a stash @ ID 0
git stash drop stash@{0}
Sometimes you need the latest revision but your current branch isn't complete enough to save away as a commit. The quick-and-easy approach is to stash those changes away. It's also useful if you're just doing a few throwaway experiments that don't justify the creation of another branch.
Branching
# Lists the branches
git branch
# Creates a branch
git branch <branchname>
# Deletes a branch (branch must be merged with HEAD)
git branch -d <branchname>
# Deletes a branch (Irrespective of its merged status)
git branch -D <branchname>
# Checks out a branch
git checkout <branch>
# Creates a branch and then checks it out
git checkout -b <branch_name>
If there is more than one dev working on a code base then you should both be working on your own branches. The master should contain the current revision of the code with nothing extra. Changes to the master should be minimized because that's what the other devs are going to pull before they merge/rebase/push their new changes.
I repeat, any code that is in flux should remain on a separate branch. This is git not SVN we're talking about. It's not like it's hard to use branches.
Patching
If you're sane, you'll restrict push access to the repository to only the most skilled/trusted developers. If a dev steps in and wants to commit some changes ask them to submit a patch (or patches). Review them closely before committing.
# Creates a patch from the last commit
git format-patch -1
# Creates a patch from the last commit
git format-patch -o ../_patch/ --start-number 0 -1
# Applies and commits a patch
git am ../_patch/*
# Applies and commits all the patches in a specified directory
git am --directory=../_patch/*
All these are convenient variations of 'git format-patch' and 'git am'. The first is obvious, the second makes is so you can create multiple patches in one shot and output them to a different folder. If you change the -1 to a different number to specify the number of commits that will be changed into patches.
Remoting
Lets say that you've been collaborating with another developer who is submitting a ton of commits but you still don't want to grant push access. Well, branching gets to be a serious pain after a while. Isn't git supposed to be capable of using branches from multiple repositories. Yes, it is and here's how.
First create a remote repository (I used to use Gitorious but YMMV). To track the link to that repository you'll need to create a remote. Think of a remote as a web link to another repository.
# Create a remote
git remote add <remoteName> <remote_url>
# Cleans the remotes
git remote prune <remoteName>
First you want to update your listing of branches so you fetch the status of the remote branches.
# Updates the status of the remote branch
git fetch
Looking at remote branches is nice but you want to make changes to those branches so you should create a remote tracking branch.
# Creates a remote tracking branch
git branch --track <remote> <branch>
When you work with a remote tracking branch it's like working with the master/origin branch. It's linked to a remote server so you can push/pull changes except it can point to a completely different repository.
The workflow for a developer using a side-repository for mainstream development is to create the remote repository. Develop/commit/push his/her changes to that repository. Then the project owner/maintainer can also checkout the same remote tracking branches to pull/QC/test those changes before merging/rebasing them into the master branch.
This is how forking a project works. A subset of the development team breaks off of the main branch and creates their own independent line of development. They may selectively pull commits from the parent project (by keeping a remote tracking branch for the master branch of the parent repository) and the parent project may selectively pull commits from the child project (by keeping a remote tracking branch for the master branch of the child repository).
The concept of local commits and the ease of branching (and remote branching) make forking a tree of development as easy as typing in a few commands.
The hardest part about git is the sucky documentation.
Note: After reading a few of the replies, I realized that I have been under-utilizing the 'fetch' command. While my old workflow was based on pulling the latest on always merging/rebasing onto a clean master branch, I can see how updating the master and doing some dry runs before merging/rebasing would save time correcting conflicts.