After reading A successful Git branching model [nvie.com], which I consider one of the best graphical/textual depictions of the ideal Git model for development teams (and most large projects), I simply wanted to adapt a similar (but way less complex) model for some of my smaller sites and multisite Drupal installs.
Since I'm (almost always) the only developer, and I develop locally, I don't want the complexity of working on many branches at once (master, hotfixes, develop, release, staging, etc...), but I do want to have a clean separation between what I'm working on and the actual live master branch that I deploy to the server.
So, I've adopted a simple 'feature branch model' for my smaller projects:
- master - the live/production code. Only touch when merging in a feature or simply fixing little bugs or really pressing problems.
- [issue-number]-feature-branches - Where I work on stuff.
Graphically:
Any time I work on something more complicated than a simple styling tweak, or a fix for a WSOD or something like that, I simply create a feature branch (usually with an issue number that matches up to my internal tracking system). Something like 374-add-node-wizard:
# create (-b) and checkout the 374-add-node-wizard branch.
$ git checkout -b 374-add-node-wizard
While I'm working on the node wizard (which could take a week or two), I might make a couple little fixes on the master branch. After I make the fixes on master (switch to it using $ git checkout master
), I switch back to my feature branch and rebase my feature branch:
$ git checkout 374-add-node-wizard # switch back to the feature branch
$ git rebase master # pull in all the latest code from the master branch
I can also create simple .patch files off a branch to pass my work to another server or a friend if I want (I like using patches instead of pushing around branches, simply because patch files are easier for people to grok than more complicated git maneuvers):
# create a diff/patch file from the checked out branch.
$ git diff master..374-add-node-wizard > 374-add-node-wizard-patch.patch
When I finish my work on the feature branch, I switch back to master, merge in the branch, and delete the branch. All done!
$ git checkout master # switch back to master
$ git merge --no-ff 374-add-node-wizard # merge feature branch back into master
$ git branch -d 374-add-node-wizard # delete the feature branch
Finally, I test everything to make sure it's working fine in master, and then push the code changes up to the server.
Since I'm developing alone, this is a lot easier than a more complicated branching setup, and it allows me to work on as many features as I want, without fear of messing things up on master, or having merge conflicts (I rebase early and often).
(Note: I usually work in the command line, because I'm more comfortable knowing what git is doing that way... but I often open up Tower (imo, the best application for visual Git) to inspect branches, commits, and merges/rebases... some people would probably rather just use Tower for everything).
(Note 2: When creating patches to send to someone that include binary files (like a png or a gif, jpeg, whatever), make sure you use $ git diff --full-index --binary [old]..[new] > patchfile.patch
so git doesn't barf when you try applying the patch on someone else's end...).
Comments
IMO, this is also a good way to submit drupal patches; checkout the project (or drupal core), create a feature branch locally, make changes (and continue to rebase), then when you want to file patches, just make the patches using
git diff [main]..[local] > [drupal.org_issue]-[comment].patch
The 'advanced patch contributor guide' says something to this effect, but gets a bit caught up in the details...
I think this is a great workflow, I use something very similar, thanks for sharing!
If you use the git flow scripts it is very, very easy to stick with the branching model of nvie.com. https://github.com/nvie/gitflow
I use that on a daily basis and could not think of doing witout.
While for just sharing changes
git diff
is OK, when you send patches for inclusion it is better to usegit format-patch
IMHO, this way IF the maintainer is kind enough to apply it usinggit am
the authorship is preserved and you get the credit you deserve.You can put multiple commits in a single patch using
git format-patch --stdout
but remember to double check what you are actually sending and, if needed, usegit rebase -i
to cleanup the history of your local branch before producing patches.Just my 2 cents.
Thanks,
Antonio
Great post Jeff! Easy to understand and simple to follow.
Thanks, It is a simple yet very useful tutorial. It helps me have a better organisation of my branches.
I'm was looking for an easy way to make version control for me as the only developer. And your way is a fine cut down of the greater model from nvie.
But what I'm missing, what I'm needing too, is a way to version control the database too.
Is there an easy way to do "git checkout state-before-a-change-that-changes-the-db" and I have that state of the code AND of the db of this branch?
You might want to read through this post on using drush to sync databases, as well as the comments on that post. Databases are a much trickier problem.
Thanks for the link.
It seems there are different ways to cope with the problem of versioning databases. And the contents of the side and those of the comments are interesting.
I use a very similar workflow. In addition I like to tag the feature branch before I delete it:
git checkout 374-add-node-wizard
tag archive/374-add-node-wizard
That way I can always go back to a deleted branch, if I ever need/want to.
A good idea!