
A successful Git branching model - iamwil
http://nvie.com/archives/323
======
steveklabnik
This article is _awesome_. I've tried to explain this before, this is how I
develop in my startup, too.

> Unfortunately, I have not found a way to make --no-ff the default behaviour
> of git merge yet, but it really should be.
    
    
        git config branch.<branchname>.mergeoptions --no-ff
    

I believe this is what you want.

------
Sapient
Thats a lot of writing to explain a diagram which explains itself perfectly
well.

That said, it still looks like a great way to handle branches!

~~~
bryansum
Agreed. I think Tufte would be proud of that diagram.

------
herdrick
Someone should write a graphical frontend for git where you create and
manipulate a graph like that.

~~~
simonk
You mean like Github's network graph?

~~~
herdrick
Not for just visualization but for control also. You drag and drop and point
and click to branch, merge, etc.

~~~
rbanffy
Real programmers use the keyboard ;-)

I use to joke Git was developed by people much smarter than me, for people
much smarter than me. The fact we can use it to do our jobs is nothing more
than coincidence.

------
pilif
My company is working on a - by now - quite large web application. Initially
(2004), I began with CVS and then moved to SVN and in the second half of last
year, to git (after a one-year period of personal use of git-svn).

We deploy the application for our customers - sometimes to our own servers
(both self-hosted and in the cloud) and sometimes to their machines.

Until middle year, as a consequence of SVN's really crappy handling of
branches (it can branch, but it fails at merging), we did very incremental
development, adding features on customer requests and bugfixes as needed,
often times uploading specific fixes to different sites, committing them to
trunk, but rarely ever updating existing applications to trunk to keep them
stable.

Huge mess.

With the switch to git, we also initiated a real release management, doing one
feature release every six months and keeping the released versions on strict
maintenance (for all intents and purposes - the web application is highly
customizable and we do make exceptions in the customized parts as to react to
immediate feature-wishes of clients).

What we are doing git-wise is the reverse of what the article shows: Bug-fixes
are (usually) done on the release-branches, while all feature development
(except of these customizations) is done on the main branch (we just use the
git default name "master").

We branch off of master when another release date nears and then tag a
specific revision of that branch as the "official" release.

There is a central gitosis repository which contains what is the "official"
repository, but every one of us (4 people working on this - so we're small
compared to other projects I guess) has their own gitorious clone which we
heavily use for code-sharing and code review ("hey - look at this feature I've
done here: Pull branch foobar from my gitorious repo to see...").

With this strict policy of (for all intents and purposes) "fixes only" and
especially "no schema changes", we can even auto-update customer installations
to the head of their respective release-branches which keeps their
installations bug-free. This is a huge advantage over the mess we had before.

Now. As master develops and bug-fixes usually happen on the branch(es), how do
we integrate them back into the mainline?

This is where the concept of the "Friday merge" comes in.

On Friday, my coworker or I usually merge all changes in the release-branches
upwards until they reach master. Because it's only a week worth of code,
conflicts rarely happen and if they do, we remember what the issue was.

If we do a commit on a branch that doesn't make sense on master because master
has sufficiently changed or a better fix for the problem is in master, then we
mark these with [DONTMERGE] in the commit message and revert them as part of
the merge commit.

On the other hand, in case we come across a bug during development on master
and we see how it would affect production systems badly (like a security flaw
- not that they happen often) and if we have already devised a simple fix that
is save to apply to the branch(es), we fix those on master and then cherry-
pick them on the branches.

This concept of course heavily depends upon clean patches, which is another
feature git excels at: Using features like interactive rebase and interactive
add, we can actually create commits that

* Either do whitespace or functional changes. Never both.

* Only touch the lines absolutely necessary for any specific feature or bug

* Do one thing and only one.

* Contain a very detailed commit message explaining exactly what the change encompasses.

This on the other hand, allows me to create extremely clean (and exhaustive)
change logs and NEWS file entries.

Now some of these policies about commits were a bit painful to actually make
everyone adhere to, but over time, I was able to convince everybody of the
huge advantage clean commits provide even though it may take some time to get
them into shape (also, you gain that time back once you have to do some blame-
ing or other history digging).

Using branches with only bug-fixes and auto-deploying them, we can increase
the quality of customer installations and using the concept of a "Friday
merge", we make sure all bug-fixes end up in the development tree without each
developer having to spend an awful long time to manually merge or without
ending up in merge-hell where branches and master have diverged too much.

The addition of gitorious for easy exchange of half-baked features to make it
easier to talk about code before it gets "official" helped to increase the
code quality further.

git was a tremendous help with this and I would never in my life want to go
back to the dark days.

I hope this additional insight might be helpful for somebody still thinking
that SVN is probably enough :-)

~~~
aaronblohowiak
_What we are doing git-wise is the reverse of what the article shows: Bug-
fixes are (usually) done on the release-branches, while all feature
development (except of these customizations) is done on the main branch (we
just use the git default name "master")._

I would just like to point out to git newbies that there is nothing special
about the master branch in git except that it is a reasonable default. In
terms of working on the release branch or working on master, there are no
extra features or support from git, so the trade-off is only in what is easier
for you and your team to remember.

~~~
pilif
exactly. I used the term master because that's what we are using internally.
We could have called it foobar of course :-)

For the poster of the article, a stable (i.e slow moving) master was
important, for us stable release branches.

The head of their master only uses as new releases are made. Our master moves
constantly and releases are tagged on the release-branches.

It's really just a matter of terminology though.

Another point I wanted to make with my post was that you don't need as many
branches as the original article for quite the same advantages.

------
tlack
I wish I could decipher my mental blockage with understanding git's model of
development.

~~~
kscaldef
I think the mistake you're making is in thinking that git _has_ a model of
development. It doesn't. It's an extremely flexible set of tools which you can
build many development models and branching strategies from.

~~~
rbanffy
Or, to use a tired image, "There is no spoon".

------
z8000
Every time I see "daily" misspelled as "dialy" I read it like Bialystock and
end up quoting _The Producers_. This kind of thing happens to me a lot. It's
like my subconscious _wants_ wants me to be distracted easily!

~~~
nvie
I've fixed it for you. Sorry for the distraction :)

~~~
z8000
Heh, now my comment does not make any sense! Oh well. :)

------
artagnon
You've given quite a high-level overview. Although it shows the advantages of
branching and merging, re-writing history is where Git really shines.

> Unfortunately, I have not found a way to make --no-ff the default behaviour
> of git merge yet, but it really should be.

No, it shouldn't. It's just your personal preferences. I can give you plenty
of examples where --no-ff makes little sense.

~~~
chrisduesing
Would you? As someone who is new-ish to Git the author's argument seemed
pretty sound. I would be interested in counter points.

------
iamwil
I didn't think y'all be so interested.

[http://www.perforce.com/perforce/conferences/us/2005/present...](http://www.perforce.com/perforce/conferences/us/2005/presentations/Wingerd.pdf)

<http://video.google.com/videoplay?docid=-577744660535947210>

there's more tasty delight.

------
moe
Probably boils down to taste but after reading the article I still like this
workflow better: [http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-
te...](http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html)

------
jackchristopher
Slightly off topic but the Git model is generally interesting. I'd like to see
it used for writing, publishing and sharing ideas (like it can code). To me it
seems like it could be a great system.

~~~
jefurii
Check out flashbake. It's a set of Python scripts for automating git and
adding various metadata to commit messages, and was written as a personal
writing tool for Cory Doctorow.

<http://wiki.github.com/commandline/flashbake/>

------
DannoHung
If you had to, how would you backport a fix onto an earlier release using
this?

Or is that something that's not considered as necessary? (This is used for a
website, for example?)

~~~
spc476
As pilif said, use "git cherry-pick". I do that for a web application I'm
responsible for. It needs to support both MySQL and PostgreSQL, and due to a
few inconsistencies (mainly, dates and enums) I'm currently maintaining two
parallel branches of the application. If I do a bug fix that isn't database
specific, I'll commit to the branch I'm working on, and cherry-pick that
change into the other branch.

Yes, it's not as clean as I first expected it to be (and I'm working on
merging the two into a single branch) but at least it's possible to do that
with git.

~~~
DannoHung
Maybe pilif has a better example, but I don't think that necessarily applies
to backporting a fix. Reason being that you can't cut the new release of the
backported version on the master branch without doing a history rewrite. You
could certainly have it on a separate branch off of the release version (of
course), but then you have to keep that branch (which may or may not be a
problem).

~~~
pyre
You could create that branch and then update the tags (IIRC, git-tag changes
propagate). In general though, you're probably better off with separate
branches for each major code change if you're business is obligated to support
older versions (e.g. firefox-1.5, firefox-2.0, etc branches rather than
relying solely on tags).

------
jbert
That's great. My initial impression of the graph is that it looked over-
complex. But it was explained well.

I guess you could take some shortcuts (e.g. commit hotfixes to develop and
cherry-pick them into master) but the described flow is a clean way of doing
it. (And the cheap branching etc means that such a shortcut doesn't really buy
you anything.)

------
philjackson
Interestingly, we've implemented this model with SVN except:

* where he has 'develop' we use /trunk

* we've /tags/ where he has master (and git style tags)

Along with this; git-svn gives those of us who use it at least some of the
benefits of git, like rewriting before pushes and stashing.

------
JeffJenkins
This is approximately what the company I work at does, except for us "develop"
is called "master", "master" from this diagram doesn't exist, and the tags are
made off the tip of the release branches.

------
aupajo
I tend to rebase branches rather than merge. Anyone have any thoughts on this?

~~~
albertcardona
Yes: that you rewrite history. I find it not very useful outside private
changes in topic branches.

~~~
pilif
I guess the OP was referring to rebasing before merging into the target
branch.

This makes the history look much nicer.

While it's rewriting history, the only part of the history you change is the
parent of the first commit on your branch and you are doing it on your private
branch before merging it into the public one.

This is a totally standard practice and used by many people. In fact, at my
place we have the policy of generally not doing non-ff merges into the main
integration branch, so the history on the integration branch is always linear.

