A successful Git branching model(nvie.com)
nvie.com
A successful Git branching model
http://nvie.com/archives/323
47 comments
Someone should write a graphical frontend for git where you create and manipulate a graph like that.
You mean like Github's network graph?
Not for just visualization but for control also. You drag and drop and point and click to branch, merge, etc.
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.
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.
gitk already does that, doesn't it?
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 :-)
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 :-)
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.
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.
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.
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.
Great post. I implemented SVN in an environment that did not have any source control, so it was not easy to move folks to a branching model within SVN. Maybe doing git would be easier.
Been looking into the best way to do this, since the individual branch model might work easier for doing tag, release, feature, and stable branches. But mainly if it could simplify merging, which is a little more painful in SVN I think, even using a basic model. So many conflicts come up that I wouldn't think should be an issue.
Any thoughts or links would be appreciated. Thanks.
Been looking into the best way to do this, since the individual branch model might work easier for doing tag, release, feature, and stable branches. But mainly if it could simplify merging, which is a little more painful in SVN I think, even using a basic model. So many conflicts come up that I wouldn't think should be an issue.
Any thoughts or links would be appreciated. Thanks.
Just so I understand this right, you have separate, customized installations of your application per customer? So, that you have individual release-* branches for each customer (or at least for those you've customized things for). It sounds like you're just adapting to your own particular needs, which are for a single release version of the product in the OP's case. Different strokes for different folks. It goes to show the incredible flexibility of Git. It's too awesome :)
I wish I could decipher my mental blockage with understanding git's model of development.
It takes a while to fully grok git, but I recently found a really good presentation which has helped my co-workers get up to speed really quickly.
The most important tip for understanding git is probably to actually start using it.
edit: Forgot the link http://gitcasts.com/posts/railsconf-git-talk
The most important tip for understanding git is probably to actually start using it.
edit: Forgot the link http://gitcasts.com/posts/railsconf-git-talk
I have the same problem. Everyone is always saying how easy merging is, but if two developers work on the same code it's going to be hard to reconcile no matter what git can do. Merging is merging is merging. If, for example, I make a change to a file and another developer refactors it out of existence there's no tool out there that's going to automatically figure out the merge. Someone has to sit down and spend some brain cells to figure it out, whether he's using git or subversion.
To be precise, Git makes merges easy, not merge conflicts, which is what you're talking about. Handling merge conflicts automatically is AI-complete. But many SCM systems make even straightforward merges difficult.
Well then I REALLY don't get it. I can branch and merge all day in my scm if there aren't any conflicts. Is all the hype over git just because maybe the branch and merge commands are slightly simpler?
Git helped us out a lot in that it tracks content, not files. So where one person might do some cleanup that included renaming some files, and another might make some changes to the same files our previous source control system either choked or just ignored the changes.
Also, we were spending a very large amount of time waiting for merges to complete. Minutes. Lots of them. Git is lightning fast, and we spend a lot less cycles waiting (or context switching).
Also, we were spending a very large amount of time waiting for merges to complete. Minutes. Lots of them. Git is lightning fast, and we spend a lot less cycles waiting (or context switching).
No. Read this:
http://whygitisbetterthanx.com/
I would say the primary "hype" factor of git is because of local commits and all the infrastructure/features around them. Better server-side merges is just a nice bonus.
http://whygitisbetterthanx.com/
I would say the primary "hype" factor of git is because of local commits and all the infrastructure/features around them. Better server-side merges is just a nice bonus.
Having a local backup of the repo and making branching/merging very cheap reduces the friction in several VC operations. You can use techniques such as bisect* without cumulative network latency disrupting your train of thought. Also, when throwaway branches are cheap, you'll probably find you use them quite a bit more.
* For finding what commit introduced a bug, by binary search. Flag a revision as the last known good commit, then bisect will switch to a one in-between, wait for you to test and mark it as good or bad, then repeat. Better yet, just provide a test suite and it will classify the revision automatically.
It's somewhat comparable to incremental programming with a REPL, rather than a compile-link-test cycle. Sure, you only get feedback on your code "slightly faster", but that makes a tremendous difference.
Git is hyped pretty hard (software hipsters seem to be gaga over it, probably in part because of gasp Linus), but if you ignore all that, it is a pretty good version control system.
* For finding what commit introduced a bug, by binary search. Flag a revision as the last known good commit, then bisect will switch to a one in-between, wait for you to test and mark it as good or bad, then repeat. Better yet, just provide a test suite and it will classify the revision automatically.
It's somewhat comparable to incremental programming with a REPL, rather than a compile-link-test cycle. Sure, you only get feedback on your code "slightly faster", but that makes a tremendous difference.
Git is hyped pretty hard (software hipsters seem to be gaga over it, probably in part because of gasp Linus), but if you ignore all that, it is a pretty good version control system.
[deleted]
I didn't grok git until I found out that it's just magic. --> http://www-cs-students.stanford.edu/~blynn/gitmagic/
I found that document rather more useful in getting me started than the official man pages. :)
I found that document rather more useful in getting me started than the official man pages. :)
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!
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.
> 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.
Would you? As someone who is new-ish to Git the author's argument seemed pretty sound. I would be interested in counter points.
I didn't think y'all be so interested.
http://www.perforce.com/perforce/conferences/us/2005/present...
http://video.google.com/videoplay?docid=-577744660535947210
there's more tasty delight.
http://www.perforce.com/perforce/conferences/us/2005/present...
http://video.google.com/videoplay?docid=-577744660535947210
there's more tasty delight.
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...
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.
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/
http://wiki.github.com/commandline/flashbake/
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?)
Or is that something that's not considered as necessary? (This is used for a website, for example?)
git cherry-pick can help. I'll add a bigger comment to this posting to explain how we are doing it with a web application - maybe if can yield some additional clues.
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.
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.
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).
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).
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.)
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.)
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.
* 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.
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.
[deleted]
I tend to rebase branches rather than merge. Anyone have any thoughts on this?
Yes: that you rewrite history. I find it not very useful outside private changes in topic branches.
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.
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.
[deleted]
> Unfortunately, I have not found a way to make --no-ff the default behaviour of git merge yet, but it really should be.
I believe this is what you want.