I use git for projects I maintain and I try to use it
where possible in group projects. I love how I can do work offline, branching
is extremely cheap and easy, it's fast and I can make sure that my history is
clean. I'd like to write about how I use git so that others can learn from it
and that I may also get feedback on how to improve my workflow.
Today I'd like to go over what are known as "feature" or "topic" branches.
These are especially useful when you are working with multiple remote
repositories, but are also useful for your solo projects. I'll be going over
it through an example I hit recently with the two remote repository situation.
This usually happens when you have read-only access to the upstream repository
and you create your own fork of it so that you have write access to a public
repository. Your repository is so that patches you write can be pulled by
upstream to merge changes you make into upstream more easily.
For Firmant, I have my own repository that I publish my changes
to configured as the cledwyn whereas the official upstream is configured as
origin. This is so that Rob may pull from my server and merge my changes
from there rather than emailing sets of patches around.
One issue that arises from this is when you push to your repository on
master while upstream pushes different code to their master. Since
these are public repositories, a force push should not be used, but in this
situation, one of the repositories has to be force pushed or merge commits
(which I like to avoid when just updating code from a remote repository) would
need to be made. Upstream is the worse choice here since it is the official
repository. How should one avoid this issue altogether? Since git makes
branching easy and fast, this is easy to avoid.
Say that I were to work on the LaTeX feature targeted
of Firmant 0.4. If I were to develop on my master branch, I would have to
keep rebasing and force-pushing to my repository if I wanted to keep it public
somewhere and up-to-date with the latest changes upstream is making without
those pesky merge commits. The other possibility is to use a branch to develop
the LaTeX functionality. To create this branch, I would issue the following
git command:
% git checkout -b dev/latex
This creates a branch named dev/latex and makes it the current HEAD.
From here, I can work on the LaTeX code without worrying about clashing
branches with upstream. When I am done with the feature (properly documented
and tested of course), I can ask Rob to merge my branch into his master.
In order to keep the topic branch up-to-date with master, I merge the
master branch into the dev/latex branch:
% git merge --no-ff master # (1)
% # Edit merge conflicts # (2)
% git add file1 file2 # (3)
% git commit # (4)
Here's a description of what is happening:
- Merge the changes that have occurred upstream into the dev/latex
branch. If all goes well, steps 2 and 3 will be taken care of by git.
The --no-ff option ensures that a merge commit is made (this is one
instance where they are convenient to have, but I'll post about that
later).
- Fix any merge conflicts.
- Add files that conflicted.
- Commit the changes.
This keeps my feature branch up-to-date and also allows my master branch
to track upstream's master. When I request that Rob merge my commits, I
would mention that the dev/latex branch should be merged into master.
Since branches are cheap, I can keep many different topic branches around for
various features so that the history for each feature is easily visible and
not intermixed with things like commits fixing typos or bugs. This allows a
cleaner history to be made so that you can follow the development of a feature
instead of having to sift it out from the entire changeset since the feature
was started.
In other version control systems, every feature branch would be a complete
copy of master which, for large code bases, can become unwieldy and a mess.