I think, and I might be wrong, that one of the things that's most misunderstood about git is its distributed nature. This makes it very different to say subversion in the ways you can work although you can mimick SVN behaviour should you want. The problem is pretty much any workflow will do, which is great but also misleading.

If I have my understanding of kernel development (I'll focus on that) right, everyone has their own git repository for developing the kernel. There is one repository, linux-2.6.git, looked after by Torvalds, that acts as the release repository. People clone from here if they wish to start developing a feature against the "release" branch.

Other repositories do some development. The idea is to clone from linux-2.6, branch out as many times as you like until such a point as you've got a working "new" feature. Then, when this is ready, you may make it available to someone considered trusted, who will pull this branch from your repository into theirs and merge it into the mainstream. In the linux kernel this happens on several levels (trusted lieutenants) until it reaches linux-2.6.git at which point it becomes "the kernel".

Now here's where it gets confusing. Branch names don't need to be consistent across repositories at all. So I can git pull origin master:vanilla-code and get a branch from the origin 's master in a branch in my repository called vanilla-code . Providing I know what's going on, it really doesn't matter - it is distributed in the sense that all repositories are peers to each other and not just shared across several computers like SVN.

So, with all of this in mind:

I think it is up to each programmer how they do their branching. All you need is a central repository for managing releases etc. Trunk could be head . Releases could be tags or branches and hotfixes are probably branches in themselves. In fact, I'd probably do releases as branches so you can keep patching them. I would merge and not rebase. If for example you take a repository, clone it, branch and do some dev, then pull from your origin you should, in your repository, probably make another branch and merge the latest master into yourbranch so that someone else can pull your changes with as little effort as possible. There is very rarely a need to truly rebase, in my experience. I think it's a case of understanding the way Git works and what it can do. It does take a while and a lot of good communication - I only truly started to understand what's going on when I began using git with other developers and even now, some things I'm not sure about. Merge conflicts are useful. I know, I know, you want it all to work, but, the fact is code changes and you do need to merge the results into something that works. Merge conflicts are in fact just more programming. I've never found an easy explanation for what to do about them, so here it is: note the files that have merge conflicts, go and change them to what they should be, git add . and then git commit . However it suits. As I've said, each users git repository is their own to play with and branch names don't need to be the same. If you had a staging repository, for example, you could enforce a naming schema, but you don't need to for each developer, only in the release repo. This is the merge stage. You only merge into release branches etc when you consider code to be reviewed/pass quality testing.

I hope that helps. I realise VonC as just posted a very similar explanation... I can't type fast enough!

Edit some further thoughts on how to use git in a commercial setting, as this seems relevant to the OP from the comments:

The release repository, we'll call it product.git , is accessible by a number of senior programmers / technical people responsible for actually looking after the product itself. They are analogous to the role of maintainers in OSS.

, is accessible by a number of senior programmers / technical people responsible for actually looking after the product itself. They are analogous to the role of maintainers in OSS. These programmers probably also in part lead development of new versions, so they might also code themselves and maintain varios repositories. They might manage staging repositories for really new features and they might also have their own repositories.

Below them are programmers responsible for developing individual bits. For example, someone might be responsible for the UI work. They therefore manage the UI.git repository.

Below them are the actual programmers who develop the features as their full day to day job.

So what happens? Well, everyone pulls at the start of each day from the "upstream" source i.e. the release repository (which will also probably contain the latest material from the previous days development). Everyone does this, directly. This will go on a branch in their repository, probably called "master" or maybe if you're me called "latest". The programmer will then do some work. This work might be something they're not sure about, so they make a branch, do the work. If it doesn't work, they can delete the branch and go back. If it does, they will have to merge into the main branch they're currently working on. We'll say this is a UI programmer working on latest-ui so he does git checkout latest-ui followed by git merge abc-ui-mywhizzynewfeature . He then tells his technical lead (the UI lead) hey, I've completed such a task, pull from me. So the UI lead does git pull user-repo lastest-ui:lastest-ui-suchafeature-abc . The UI lead then looks at it on that branch and says, actually, that's very good, I'll merge it into ui-latest . He might then tell everyone below him to pull from him on their ui-latest branches or whatever name they've given them, and so the feature gets explored by the devs. If the team is happy, the UI lead might ask the testing lead to pull from him and merge the changes. This propagates out to everyone (downstream of the change) who tests it and submits bug reports etc. Finally, if the feature passes testing etc, one of the top technical leads might merge it into the current working copy of the program, at which point all the changes are then propagated back down. And so on.

It's not a "traditional" way of working and is designed to be "peer driven" rather than "hierarchical" like SVN/CVS. In essence, everyone has commit access, but only locally. It is access to the repository and which repository you designate as the release repo that allows you to use hierarchy.