Over the Christmas holidays I took a break from translating and editing the
book on quality assurance in PHP projects
that I am working on to finally migrate the code repository of
PHPUnit from a self-hosted
Subversion repository to a
Git repository that is hosted on
GitHub.
How did I get here?
I was staying at Arjen's place in Brisbane
in August 2008 and one day we talked about distributed version control. Although I
knew the basic concepts behind it, I was not yet convinced enough to take the
plunge and try it out. Our discussion changed that, but it was not until my
second trip to Australia later that year that I took the initial code for
PHP_ObjectFreezer (which I had on my laptop since I started to hack on it
together with Stefan on the flight to
Atlanta for php|works 2008) and put it into a
bzr repository on
Launchpad. I grew comfortable enough with
bzr quickly, but never really warmed up to Launchpad.
Around that time, I was hearing more and more positive things about Git and
GitHub from my peers. So I took the PHP_ObjectFreezer code base and migrated it
to Git and hosted the repository and GitHub to experiment with both the tool and
the platform. It was a step that I did not regret and all the projects that I
started since then are hosted on GitHub:
bytekit-cli,
phpcpd,
phpdcd,
phploc,
PHP_CodeCoverage,
PHP_FileIterator,
PHP_ObjectFreezer,
Text_Template,
PHP_TokenStream.
Why did I do this?
Let me start with a quote from GitHub.com:
- Git is a fast, efficient, distributed version control system ideal for the collaborative development of software.
- GitHub is the easiest (and prettiest) way to participate in that collaboration: fork projects, send pull requests, monitor development, all with ease.
Over the last year, I have come to appreciate Git and GitHub a lot and also
wanted to use them for PHPUnit.
Sure, I could have used git-svn
for bi-directional operation between the existing Subversion repository and Git,
but this would have always felt like only going half the way.
The arguments in
favour of distributed version control systems are discussed by others far better
than I could discuss them here, so I will just quote Ian Clatworthy's
paper on distributed version control systems,
in which discusses not only the technical differences between traditional
version control systems and distributed version control systems, but also the
differences with regard to development workflows and developer interaction:
- Developers can collaborate directly without needing central
authority or incurring central administration overhead
- Developers can
still be productive when the umbilical cord to their central VCS repository is
broken, e.g. when travelling.
- Creating and destroying branches are
simple operations. This is particularly useful when experimenting with new
ideas, e.g. a spike when using eXtreme Programming.
- Ad-hoc collaboration with peers [is facilitated by] intelligent merge
tracking [because] merging early and merging often is both possible and
surprisingly unpainful. It is difficult to explain just how much of an impact
this can make on how co-developers can work together more easily, e.g. when
Pair Programming.
What does this mean for you?
PHPUnit is now hosted
on GitHub.
In a nutshell, this means that the development of PHPUnit is now more open
than it was before. If you want to contribute, you just need to
fork PHPUnit on GitHub and create
a topic branch for your
contribution. Then let me know about your topic branch and I may or may not
merge it.
If you are currently using svn:externals
to pull PHPUnit into your own Subversion repository, you need to think about an
alternative as PHPUnit's Subversion repository is no longer updated and will
eventually go away.
How did I do it?
As this might be of interest to someone who wants to migrate his/her repository
from Subversion to Git, here is how I performed the migration.
I started by creating a local mirror of the Subversion repository:
# Fetch Subversion repository
svnadmin create phpunit.svn
cat <<'EOF' > phpunit.svn/hooks/pre-revprop-change
#!/bin/sh
USER="$3"
if [ "$USER" = "svnsync" ]; then exit 0; fi
echo "Only the svnsync user can change revprops" >&2
exit 1
EOF
chmod +x phpunit.svn/hooks/pre-revprop-change
svnsync init \
--username svnsync \
file://`pwd`/phpunit.svn \
svn://svn.phpunit.de/phpunit
svnsync sync \
--username svnsync \
file://`pwd`/phpunit.svn
Then I used svn2git for the
actual migration:
# Create directory for Git repository
mkdir phpunit.git && cd phpunit.git
# Use svn2git to import repository
svn2git \
--trunk trunk \
--branches branches/release \
--tags tags \
--authors /home/sb/authors.txt \
file:///home/sb/phpunit.svn/phpunit
After that I had to delete quite a few superfluous branches and tags, but that
quickly dealt with. The final step was to create common ancestors for the master, 3.5, and 3.4 branches so that merging becomes easy and painless.
# Create 3.5 and 3.4 branches (in local repository)
git checkout remotes/origin/3.5 -b 3.5
git checkout remotes/origin/3.4 -b 3.4
# Create common ancestors for the master, 3.5, and 3.4 branches
git checkout 3.5 && git merge --strategy=ours master
git checkout 3.4 && git merge --strategy=ours 3.5
git checkout master && git merge --strategy=ours 3.5
git checkout 3.5 && git merge --strategy=ours 3.4
After that I had to delete quite a few superfluous branches and tags, but that
quickly dealt with.
At this point I would like to thank David Soria Parra
who helped me figure out some details here and there.
Update: GitHub now supports Subversion clients:
svn co https://svn.github.com/sebastianbergmann/phpunit