Related: GitTips
git is an extremely powerful tool once you really get to know it, but many factors conspire to make it very difficult for a beginner to just start contributing to a project without reading a whole manual. git was originally designed with a particular workflow in mind -- the Linux kernel, which has a hierarchical maintainer structure and only one person maintains the authoritative repository -- and a lot of those design decisions are still with us today.
As of git 1.7.6, there have been some improvements to make your workflow easier, like more informational messages, but there's still a pretty steep learning curve, especially for people working with a shared remote repository.
The staging area
Despite having the ability to be extremely useful, this is one of the first
stumbling blocks for new git users, and it's entrenched in everything git does.
Also known as the cache or index, it comes between you and a simple git
commit that just checks in everything that has changed in your copy or
git diff that shows you all the differences between the last commit
and your changes. The output of git status has been improved over the
years to give you the exact commands you need to run for common operations, but
the staging area is still mostly a hindrance for beginners.
Pulling always merges by default
The recommended workflow for git involves creating a new branch for every
change, no matter how small, but beginners aren't used to that, and branching in
many other systems is scary and expensive. If I commit a change in my local
master branch, and the matching remote master branch has newer updates
before I push my changes, doing a git
pull always does a merge. This is needed if I'm sharing my local
repository with multiple people, but a rebase would be better if I only ever
push/pull from a single repository and never merge any branches, so that a
linear history is preserved. A merge in the case of local differences adds an
extra merge commit to the log, which is unnecessary and harder to read later
on.
Push does not set up tracking by default
Another common point of confusion is that the first time a branch is pushed up
to a remote, tracking is not set up automatically, so a subsequent pull or push
does not work by itself. There is push -u or branch
--set-upstream to automatically set up tracking (and even works on
already-existing local branches), but there is no way to make this the default
for push.
Managing Tags
Tags are great if there's only one person who manages them, but for a shared
repository they can get pretty hairy. They're not treated like normal commits.
You can't really modify or delete tags that have already been pulled by someone
else, and there's no mechanism for merging tags created by different people. It
might be a lot better if tags acted like git notes.