Rebase-based simple Git workflow
The simple workflow I want to describe has two guiding principles:
- develop is always production-like and deployable
- rebase during feature development, explicit (non fast-forward) merge when done
Pulling change-sets using rebase rewrites the history of the branch you’re working on and keeps your changes on top.
Armed with these guiding principles let’s breakdown the seven steps:
1. Start by pulling down the latest changes from develop
This is done easily with the common git commands:
git checkout develop git fetch origin git merge develop
I like to be more explicit and use fetch/merge but the two commands are equivalent to:
git pull origin develop.
2. Branch off to isolate the feature or bug-fix work in a branch
Now create a branch for the feature or bug-fix:
git checkout -b PRJ-123-awesome-feature
The branch name structure I show here is just the one we use, but you can pick any convention you feel comfortable with.
3. Now you can work on the feature
Work on the feature as long as needed. Make sure your commits are meaningful and do not cluster separate changes together.
4. To keep your feature branch fresh and up to date with the latest changes in develop, use rebase
Every once in a while during the development update the feature branch with the latest changes in develop. You can do this with:
git fetch origin git rebase origin/develop
In the (somewhat less common) case where other people are also working on the same shared remote feature branch, also rebase changes coming from it:
git rebase origin/PRJ-123-awesome-feature
At this point solve any conflicts that come out of the rebase.
Resolving conflicts during the rebase allows you to have always clean merges at the end of the feature development. It also keeps your feature branch history clean and focused without spurious noise.
5. When ready for feedback push your branch remotely and create a pull request
When it’s time to share your work and solicit feedback you can push your branch remotely with:
git push -u origin PRJ-123-awesome-feature
(if the branch is already set as ‘upstream’ and your remote is called ‘origin’, ‘git push’ is enough)
Now you can create a pull request on your favorite git server.
After the initial push you can keep pushing updates to the remote branch multiple times throughout. This can happen in response to feedback, or because you’re not done with the development of the feature.
6. Perform a final rebase cleanup after the pull request has been approved
After the review is done, it’s good to perform a final cleanup and scrub of the feature branch commit history to remove spurious commits that are not providing relevant information. In some cases – if your team is experienced and they can handle it – you can rebase also during development, but I strongly advise against it.:
git rebase -i origin/develop
(At this point if you have rewritten the history of a published branch and provided that no one else will commit to it or use it, you might need to push your changes using the –force flag).
7. When development is complete record an explicit merge
When finished with the development of the feature branch and reviewers have reviewed your work, merge using the flag –no-ff. This will preserve the context of the work and will make it easy to revert the whole feature if needed. Here are the commands:
git checkout develop git pull origin develop git merge --no-ff PRJ-123-awesome-feature
If you followed the advice above and you have used rebase to keep your feature branch up to date, the actual merge commit will not include any changes; this is cool! The merge commit becomes just a marker that stores the context about the feature branch.
8. The last step
After successfull merge just run:
git push -u origin develop