Last updated November 24, 2013.
Git concepts and how they relate to Drupal
Git is a distributed version control and source code management system which Drupal development community uses to manage all the revisions of every file that makes up the Drupal system. If you are unfamiliar with Git, check out the Git reference or the official Git tutorial before reading this. There are also many handy Git cheat sheets, containing lists of commonly used commands for easy reference. Additional links can be found at the Other Git resources page.
In Git, a repository is a data-structure which contains snapshots of files and directory trees, taken at different points in time. As a whole, the repository provides a complete history of the changes made to a project, from its initial commit, or snapshot.
Using a Git client you may clone repositories, making local copies of a project for development. With some version control systems, such as CVS and Subversion, you typically only receive a specific snapshot from the project repository. With Git, you receive a local copy of the entire repository (all snapshots).
Each project which is part of the Drupal system has its own source-code repository. There is a single repository for the Drupal core project, as well as individual projects for community-contributed modules and themes.
Commits, tags, and heads
Each snapshot of files in a Git repository is called a commit. In addition to references to file objects, a commit includes an explanatory message, information about the author, and references to the parent, or prior commit. Each commit has an automatically generated name called a ref (a 40-byte hexadecimal SHA1 code).
Any commit may be branded with a tag, or human-readable alias. In the Drupal core project there are tag names for each release (e.g., 6.18, 6.19, 7.0-beta1, 7.0-rc-1, etc). Like commits, tags may have an explanatory message stored with them. A special kind of alias called head points to the latest commit.
Branches and HEAD
A repository branch is an alternate line of development in the life of a project.
If you had some experience with Open Source software, you might be used to find the active line of development in the master branch.
While Drupal repositories might also have a legacy master branch, Drupal core and most contrib repositories switched to using major branches only. They represent the current development branch (i.e. 8.x), as well as the current production branch (i.e. 7.x) and older versions of Drupal which are still maintained (e.g. the 6.x branch).
In your local repository, you might also create minor branches to develop experimental features for a project, or to test patches other developers have made.
Each development branch has its own head alias which points to the most recent commit in that branch. While working on a project you'll only have one branch active at a time. You can refer to the most recent commit in the branch you're working on with the alias HEAD.
Repositories as growing trees
It might be helpful to use an analogy to think about branches and tags. Imagine a living tree as it grows. At some point early in the life of the tree, it has a trunk and maybe a few small twig-like branches. As it ages, the younger, small branches grow thicker and longer, and new branches split off higher up on the trunk. Sometimes, new branches even split off from older branches. Say you wanted to keep track of how the tree was growing, and you decided to tie little paper tags with some word written on them whenever a branch first split off, and periodically along the length of branches, so you could see how far the branches grew over time. To help you make sense of it, you use red paper for the tags at the start of the branches (and the word on those was a silly name you used to uniquely identify that particular branch), while the tags at different points along the length of each branch use green paper.
With this growing tree in mind, the branches on the tree would correspond to... that's right... branches in Git. The only difference is that in Git, you can decide when and where new branches split off and also branches can merge together in Git. The red paper tags at the start of each branch allows you to identify that particular branch. The green-colored tags at the ends of branches are known in Git as tags.
To continue the analogy (and translate it into software) each branch on the tree corresponds to a different major version of Drupal core (for example 6.x or 7.x). As bugs are fixed in a given release, the branch where the changes are committed would be growing longer (more revisions on that branch). Whenever a release is made, we take the most recent changes of the files (the revisions on the end of the branch) and add a tag to identify it (a marker with a word on it, in this case, based on the version number of the release) and tie it around the end of the branch. Therefore, for a contributed Drupal module, the tag at the base of the branch might be 7.x-1.0, but at the end of the branch it would be a higher number such as 7.x-1.9.
In the contributions repository, it is now possible for project maintainers to create multiple branches that are all compatible with the same version of Drupal core. In other words, a new, younger branch splits off of an older, more mature branch, instead of branches always coming off of the trunk of your tree. It's all still associated with the same basic branch (at least in terms of where it split from the trunk—a given version of Drupal core) but there are now separate branches where you make independent changes (new features) that don't disturb the natural growth of the original branch (stable code for bug fixes and security patches). As always, you can tie your paper tags to the ends of these branches and label how far they have grown whenever you want (to make a new release).
Consider the following example. You maintain a contributed module on drupal.org that includes a version for Drupal 6.x and a version for Drupal 7.x. You therefore have two branches that split from the trunk: one for Drupal 6.x and one for Drupal 7.x. The first tag on the 6.x branch is labeled 6.x-1.0, and the first tag on the 7.x branch is labeled 7.x-1.0.
You actively add features and bug fixes to both branches. When you get to version 7.x-1.9, you decide to make major changes to your code that warrant a new branch. At this point a new branch, 7.x-2.x, splits off from your existing branch. The reason this new branch splits from the existing 7.x-1.x branch and NOT from the trunk is that it supports the same major Drupal release, Drupal 7.x. You continue to add bug fixes and security updates to your 7.x-1.x branch, releasing version 7.x-1.10, 7.x-1.11, and so forth, even as you release enhancements for the 7.x-2.x branch with versions 7.x-2.1, 7.x-2.2, etc.