I tend to jump from project to project a lot, so it's nice for me to be able to keep track of that by being able to see the separate changes I've made over time as well as a description of what I changed. So rather then keep around a set of patches and a log book, I use a version control system. My choice of vcs/scm/rcs is git. Git is pretty cool, it's distributed, very fast written in C and sh with minimal external dependencies, and it's insanely powerful.
Git provides a version control system that's implemented with the UNIX philosophy in mind. Instead
of providing a monolithic tool that does a set of operations that make a vcs possible, git provides
all the tools that make up the monolithic tool. This makes it very easy to string together git tools
to do nearly anything I could want. An example of this is a tool like git-rev-parse. git-rev-parse
returns a commit hash given a name or other identifier. For example, if I want to know what commit
hash is the parent of the HEAD of my repository I can do something like:
> git-rev-parse HEAD^
738865616f288809a46bc9b18ec0a90b649892d2
In and of itself, git-rev-parse is useful but does not do much for me, but most of the git tools
which accept a commit hash use it to parse the commit hash, so I can pass HEAD^ to git-log and
I will get a log of changes to the given repository starting at the commit which is the parent of the
head of my repository. This makes writing any kind of tool around git very easy since the actual mechanism
is laid bare for manipulation and can be tweaked appropriately without much hassle.
I started using git because xmms2 switched from BitKeeper to git and so I had to learn git to be able to work on xmms2. At first I was a little put off by the low-levelness of it, but two things happened which have generally changed by mind about this:
the wrappers (or porcelain in git speak) around the low-level tools (or plumbing) became a lot better over time. When I started using git, [cogito]i(http://git.or.cz/cogito/) was basically necessary unless you were prepared to really sit down and get to know the git tools to be able to get anything done, but by now I don't even have cogito installed anymore and find that the git tools provided can do near anything I need in a way that I can actually grok.
I started to understand git a lot better. This came from playing with the git tools and realizing how a lot of the stuff worked. While I can't entirely explain this insight I can provide some tips and point out some good resources. The first thing to understand is that git doesn't really track files per-se but rather content. Which means, if you move a file, git knows you moved it because the content changed filename not because the filename changed. This is explained in a lot more detail in a post by Linus on the git mailing list. The other tip I can provide is to be aware that git follows references for you a lot. Just like git-rev-parse will figure out hashes for you, other git tools will figure stuff out for you to, so if you pass git-ls-tree a commit hash, it will read the tree hash out of the commit hash and follow that for you. This makes playing with the git tools really easy because you don't spend all your time chasing the correct hashes around.
So part of my purpose in writing this was to provide some reasons to the FreeBSD folks why git might be a good choice for a replacement for CVS. These views come from my view as a ports committer, but I think that at least some of them will apply to the src folks as well. While the ports tree is usually just hammered with a bunch of small commits all day, there are often those very large commits that can take a while to happen and cause a big fiasco. Often times we lock ports during these events to keep from introducing conflicts. This would be a great place to use branches. these kind of earth shattering changes could be worked on in a branch and then merged into the main repository this way he history of the development of the big change could be maintained in our repository instead of disappearing in one big commit. Git also provides a lot of helpful tools for easing merging which would make bring these big changes in even easier.
Distributed revision control also provides some great advantages during a freeze period. Work that is not appropriate during a freeze can be done locally in a branch and then merged into the mainline when the freeze ends. Commits that are appropriate during the freeze can be committed onto the mainline or into a branch awaiting permission to push them to the master repository. As it stands, committers currently request permission during a freeze from portmgr to commit to ports by submitting a patch and waiting for a reply. Git provides a number of tools specifically designed for submitting patches for approval. It'd also be possible for portmgr to pull commits in from committers during a freeze period.
The xorg 7.2 update was done by doing the bulk of the work on a git repository which was later merged into cvs when the work was done. This made it a lot easier to merge changes in and keep the xorg work on an up to date version of ports before D-day came. I'm taking the same approach with the Python 2.5 update, all work is being done on a branch of ports.git with periodic merges from master to keep the work up to date.
Being aware that I know considerably less about the src process I'd still like to point out some things that I
think would make the src development process easier. Merges from current are made considerably easier by using
git-cherry-pick which makes it possible to pick particular commits to be commited onto a branch. So a merge
from current would just be cherry-picking a commit from master to the STABLE branch. Much of the work that's done
in perforce could easily be done with topic branches in git as well.
There is a lot of prejudice attached to git for being a) a bit confusing at first, and b) related to Linux that I really implore everyone to look past and mess around with it for a while. Git is incredibly powerful and works really well for many a development process.