Practical Branch Layout
I’ve recently gone from being someone who uses
git entirely “on my own,” to being someone who
uses git with a lot of other people at once. I’ve also had to introduce
git to the uninitiated a few times. These have both been notable
Git is hard, particularly in these contexts: not only are there many
concepts to learn, but there’s no single proscribed workflow and a
multitude of workflow possibilities. Which is great from a philosophy
perspective, and arguably good from a “useful/robust tool perspective,”
but horrible from a “best practices” perspective. Hell, it’s horrible
for a “consistent” and “sane” practices perspective.
There are a lot of solutions to the “finding a sane practice,” when
working with git and large teams. Patching or reformulating the
interface is a common strategy. Legit is
a great example of this, but I don’t think it’s enough, because the
problem is really one of bad and unclear defaults. For instance:
- The “master” branch, in larger distributed systems is highly
confusing. If you have multiple remotes (which is common), every
remote has its own master branch, which all (necessarily) refer to
different possible points in a repository’s history.
- The names of a local branch do not necessarily refer to the names of
the remote branch in any specific repository. The decoupling of local
and remote branches, makes sense from a design perspective, but it’s
difficult to retain this mapping in your head, and it’s also
difficult to talk about branch configurations because your “view of
the universe,” doesn’t often coincide with anyone else’s?
Here are some ideas:
Have two modes of operation: a maintainer’s mode that resembles
current day git with a few basic tweaks described in later options,
and a contributors mode, that is designed with makes the following
- The “mainline” of the project’s development will occur in a branch to
which this user only has read-only access.
- Most of this user’s work will happen in isolated topic branches.
Branch naming enforcement:
- All branches will be uniquely named, relative to a username and/or
hostname. This will be transparent (largely) to the history, but will
make all conversations about branches less awkward. This is basically
how branches work now, with [remote]/[branch], except that all
local branches need self/[branch], and the software should make
this more transparent.
- Remote branches will implicitly have local tracking branches with
identical names. You could commit to any of the local tracking
branches, and pull will have the ability to convert your changes
to a self/[branch] if needed.
- All local branches, if published, will map to a single remote branch.
One remote, will be the user’s default “publication target,” for
This is basically what the origin remote does today, so again,
this isn’t a major change.
When you run git clone, this remote repository should be the
upstream repository, not the origin.
Use the origin remote, which should be the default “place to publish my
work,” and would be configured separately.
- Map local branches directly to remote branches.
- Be able to specify a remote branch as a “mirror” of another branch.
- Make cherry-picked commits identifiable by their original commit-id
internally. The goal is to push people to cherry-pick commits as much
as possible to construct histories without needing to rebase.
- Have sub-module support automatically configured, without fussing.
- Have better functions to cleaning up branch cruft. Particularly on
- Have some sort of configurable “published pointer,” that users can
use as a safe block against rebases before a given point.
The goals here are to:
- Make working with git all about branches and iteration rather than a
sequence of commits.
- Provide good tools to prevent people from rebasing commits, which is
always confusing and rarely actually required.
- Make branch names as canonical as possible. The fact that there can
be many possible names for the same thing is awful.
Who’s with me? We can sort out the details, if you want in comments.