There are a lot of Git workflows, tips, usage models, tutorials, books, and other such resources out there. Nonetheless, the issue I always encounter when introducing git to new users (both new to version control and new to decentralized version control), is that it is difficult to figure out how to make git work - end to end - for a given project.
I want to use a very straight-forward and functional workflow, highlight a simple example of git commands that can move a user about the workflow, and detail a few scenarios that highlight how the workflow applies to projects. I will claim that the workflow is very functional for many project types, although it is not my workflow. I am not claiming that these are the best commands to fulfill the workflow, nor am I claiming that successful usage of these commands is sufficient understanding to use git. I do think that these commands are some of the simplest for navigating this workflow. I also think that having these commands available as a reference will make it easier to start using git, and to start using it in a way that has the potential to use a lot more of git's functionality.
A Successful Git Branching Model (Workflow)
Vincent, over at nvie, published an excellent detail of A Successful Git Branching Model. While branching model is a more appropriate descriptor, I think non-git users would fail to find this information because the concept of a branching model is generally DVCS-specific (needs source). I use this model, or a very similar sub-structure, on many of my projects, and have nothing but good things to say about it.
Addressing the first two questions that generally surface about this git workflow:
- Yes, this workflow is appropriate even if you are a single developer or a small team.
- No, this [seemingly] excessive branching is not a waste of time.
Vincent does a great job of explaining a lot of the necessary techniques and many of the commands for keeping this branching model in order. Again, the only point I find concerning is that it generally feels like his branching model and its description target existing git users. This is fine, but I think it is a great model for git usage generally, and I also think it is straight-forward to use as a newcomer to git. In that interest, I want to spell out some functional commands to use this workflow.
Git Workflow commands
A few points, before I throw up an image. Any actual branch updates are abridged to one 'git add .' and 'git commit'. I do not condone this behavior for your branch modifications. You should commit often, that is why you are using version control. In my experience, about 95% of my projects have far more commits than I will ever need. But in the 5% of the cases where I actually needed to roll back or revert commits, I saved considerable time by commiting as often as I did.
Additionally, I have a few superfluous command techniques in place. Since I am really pushing for git newcomers to actually start (and stick to) using git, and to get others away from working in master for everything, I want to cater to those newcomers a little. In order to help them along the way, I tried to be as failsafe as possible. This is why you see things like:
git add . # Tells git to add all files in this directory to the branch git commit -am "commit details" # The -a flag tells git to add all known files before commiting. This # should not be necessary if you just ran 'git add .'
This is very directly inspired by Vincent's work, although it is obviously not meant to be a one to one replica of his branch depiction.
Git Workflow usage
If you did not actually read through the branching model explanation and details at nvie, go back and do that. Some aspects that get glossed over a bit are either just good version control habits or good git-specific habits; particularly for those of you getting started with git, I want to spell a couple of these out.
Branch. Adding some code? Branch. Adding resources that might break something? Branch. Changing a text string? Ok, maybe you can do that in the current branch, but you better make it a specific commit and give it an accurate message. What I mean is: branch more. Any discrete update might as well be a branch. Branching and merging between branches is simple with git, make use of it. I will highlight that Vincent makes a good point about using the no fast forward flag when merging; when you find gitk, you will be happy you started using --no-ff.
Use meaningful and consistent commit messages. People fight over what the consistency should be, but I am not fighting that battle here. Just be consistent. Think about things like case (initial caps?), tense (all past tense, all present, future perfect w/ negative - if you want a really interesting thought experiment when reverting), bug references (if you are using a bug tracker - you are using a bug tracker?), etc.
Some bad commit messages:
- fixing bugs
- updated issues with code working
- Replaces the images with new ones
Some better commit messages:
- Fixes bugs in form submission mechanism.
- Updates code formatting and corrects typographical errors in comments.
- Replaces the images with updated versions from version 2 marketing portfolio.
If you are working in a team, remember to pull often when working with develop and master (or any branches that will have multiple users). This will help avoid a whole nest of non-beginner-friendly error messages.
Also, don't forget this is a decentralized VCS. I only added the 'git push' commands to develop and master. It may be prudent for you to push other branches to an origin location. Origin and centralized branch techniques within teams surpasses the scope of this post, but Vincent touched on some concepts in his early discussion.
If you are coming from a centralized version control system, forget about 'git fetch' for now, 'git pull' probably does what you want. Get started and get comfortable with pull, and when you have time review the concepts behind pull and how fetch works. Fetch is really handy when you need it, but you can usually get by with pull.
Git Workflow example scenarios
I like to reserve master as a pristine representation of what went live. This represents web sites that actually spent time on the production server, libraries that are/were in use elsewhere, or applications that actually shipped. This way, if someone ever comes back and says they have a bug, you can quickly and efficiently get to the exact code that is exhibiting the issue and fix only that issue. With less complex branching models, you can get caught having to fix multiple issues, due only to the fact that you do not have a branch dedicated to your current update (I'm talking to the git users who do all their work in master...). This 'bug in a live release' example is where the master and hotfix branches shine. A word of caution - only one hotfix per hotfix branch: two hotfixes = two hotfix branches. You will thank me when you require two hotfixes and one turns out to be more problematic than you originally thought.
If you are working alone, and get hung up on a particular feature, sometimes it is very productive to shelf that feature and work on something else for a while. Instead of being stuck rigging up placeholders and dummy content, or commenting out work, go back to develop, and create a new feature branch. This gives you a fresh develop branch to update, without worrying about the partial functionality of the first feature. This is also an appropriate area of the branching model for priority changes. It may be the case that a larger feature has been downvoted, or is simply less important, and other features need your attention. The key is that a delay in one feature should never (of necessity) affect the schedule of another, independent feature. The develop and feature branches fullfil these usage cases.
The release branches are good for limiting feature creep (until you start using rebase, but that's another post). You start with what you feel to be a release candidate develop state, and then you can test against it. If there are issues, address these issues in the release branch. This provides a similar discretion to the multiple feature branches, and keeps other features from affecting your ability to address minor bugs in a release candidate. Once your release candidate is finalized, you can merge it to master, and also merge it into develop. If you are following my recommendations, at this point master gets posted, moved to production, shipped, or whatever. Be sure that if fixes were made to a release branch, those fixes are also merged back into develop. If you forget to do this your bugs will come back in the next release branch.
This got pretty long, if you made it this far, thanks for sticking around. I hope this helps flesh out a really great Git Workflow and opens git to a few new users who can hit the ground running.