So mothers keep your hackers at home
Don’t let them journey all alone
Tell them this world is full of danger
And to shun the repositories of strangers
– The Tag Set of Strangers,
(with apologies to) Nick Cave and the Bad Seeds
One of the things I love about Git is how I can add branches from remote repositories in mine at will without fearing messing up anything. The remote branches will not clash with mine, even if they share the same names, because they are referenced as repository/branch. However, as for anything else, you can still poke yourself in the eye if you try hard enough:
$ git remote bob $ git checkout -b bob/baroque Switched to a new branch 'bob/baroque' $ git fetch bob From ../bob * [new branch] baroque -> bob/baroque $ git checkout bob/baroque warning: refname 'bob/baroque' is ambiguous. Already on 'bob/baroque'
Here, I created a local branch called bob/baroque, which will end up having the same name as the branch baroque imported from Bob’s repository. Confusing, but not the end of the world. I can still see the different branches with
gitk and access the local and remote branches via
git checkout remotes/bob/baroque and
git checkout remotes/bob/baroque. The lesson to take from this, of course, is simply not to use slashes in branch names and sidestep the whole issue.
remotes/bob/baroque. I would deserve to be shot, that’s what would happen.
With tags, surprisingly, the matter is much more prickly. Not only are tags not kept in the ”namespace” of their repository of origin, but
git fetch has a very dangerous default behavior:
$ git log -n 1 somework commit 483d008c6207554236232fef4e8cd22cfb4b9bb8 Author: Yanick Champoux <email@example.com> Date: Wed Mar 3 21:14:43 2010 -0500 some work on my repo $ git fetch --tags bob From ../b - [tag update] somework -> somework $ git log -n 1 somework commit 5f7f8eddd2d44e359fe8bc0d1a2f1642d073cad9 Author: Yanick Champoux <firstname.lastname@example.org> Date: Wed Mar 3 21:15:25 2010 -0500 some work from Bob
Yup, that’s right, if there is a conflict,
fetch --tags will silently clobber the local tags with their remote counterparts. Hope you remember all the commits you painstakingly tagged in the last six months… This behavior is so mind-bogglingly dangerous that, to this day, I wonder if I’m not missing something obvious.
Now, granted, it’s fairly rare to import tags from remote repositories. But there are instances, like when adding the gitpan history of your module to your repository, where it’s relevant. In those cases, for your own sake, make sure that the remote tags won’t clash with yours. Even better, don’t use
--tags at all. Instead, do something akin to:
$ git ls-remote --tags bob | \ perl -nae'$F=~s#refs/tags#bob#; `git tag $F $F`'
This will name remote tags using the
repository/tag convention. Also, if the tag already exist, Git will complain and it won’t be clobbered by the new version.
Interested in working with Yanick? Schedule a tech call.