On Tue, Oct 08, 2013 at 07:12:22PM +0100, Tony Finch wrote:
> We often need to patch the software that we run in order to fix bugs
> quickly rather than wait for an official release, or to add functionality
> that we need. In many cases we have to maintain a locally-developed patch
> for a significant length of time, across multiple upstream releases,
> either because it is not yet ready for incorporation into a stable
> upstream version, or because it is too specific to our setup so will not
> be suitable for passing upstream without significant extra work.
Do you need to keep the modifications you make on top of upstream as a
nice, clean series of rebased patches? If not, then you can avoid the
repeated rebasing, and just use a more traditional topic-branch
workflow. Treat modifications from upstream as just another topic.
For example, start with some version (let's say 1.0) of the upstream
software as your "master" branch. If it's kept in git, build on
upstream's git history. If all you get are tarballs, create an
"upstream" branch with v1.0, and fork "master" from it.
Build on master as you would if it were your own. Fork topic branches,
develop the topics, test them, and then merge them back to "master" when
they're ready (or do development straight on master, or whatever
workflow you're accustomed to).
When v1.1 of the upstream software comes out, create a "merge-upstream"
topic branch from the tip of your "master". If upstream is in git, just
"git merge v1.1" from upstream. If not, then checkout your pristine
"upstream" branch (which should still be sitting at the v1.0 commit),
and build a v1.1 commit on top of it. And then "git merge upstream" to
pick up the new changes.
Test your merge-upstream topic in isolation, and when you think it's
ready merge it into master and deploy.
The most difficult part is the merge of upstream into the topic branch.
But git's 3-way merge tends to do a pretty good job (e.g., if you
contributed your patches upstream, then there should be no conflict).
You can also break up the work by keeping the "merge" topic running for
a long time, and merging as often as possible from upstream. That breaks
the conflict resolution into smaller chunks, and lets you do it closer
to when the conflicting patches were actually made, when they are
hopefully closer in your mind. And you don't have to worry about having
a broken intermediate result, because you're not deploying it; you're
just keeping the topic up to date until you're ready to test it.
You can also try git-imerge, which can make big merges a little more
manageable (though it can also make them harder sometimes...):
The history for such a repository might look like:
o--o--B--o--o--C <-- upstream branch
/ \ \
o--o---o--o--o--o--D <-- upstream-merge branch
/ / / \
A--o---E--o--o--F--o---G <-- master branch
\ / \ /
o--o o----o <-- topic branches
- A is the v1.0 commit you start at
- B and C are milestones where you merged upstream into your
upstream-merge topic branch. These could be releases (like v1.1), or
they could just be random spots where you felt like merging to keep
things up to date. It depends how you want to break up the conflict
- D is a state of the upstream-merge branch that you test to make sure
the merge happened OK
- E and F are merges of regular topic branches (i.e., the patches you
are working on locally). Note that we also merge those up to the
upstream-merge branch, so that we can resolve early any conflicts
between what's happening on master and what's happening upstream.
- G is the merge of D into the master branch, after we have decided
it's good to deploy
This all assumes that "master" is your known-good state that you deploy
or ship. If you prefer to have a "deploy" or "maint" branch for
hotfixes, you can do that too.
Hope that helps,
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html