This article explains how to use Mercurial and Git together for the purpose of deploying projects to Heroku...
Why Not Just Use Git?
If Heroku requires the web application to be stored in Git then you may ask, why not just use a Git repository on BitBucket?
Well, Git is great for distributed file systems, and Mercurial is great for project repositories. And Mercurial, as they proclaim on their website, just works!
Why Not Use Hg-Git?
So How Then?
Git keeps its files in a
.git directory and Mercurial keeps its files in a
.hg directory. Because of this, you can store your project in both systems at the same time. The general approach is:
- Use any Mercurial repository for source control
- Use Heroku's default Git repository (because you have to)
- Check out both repositories into the same directory
- Ensure both systems ignore each others files
- Commit, push and pull to Mercurial as required
- Only commit and push to Git to deploy the application.
In essence, Git is just used as a deployment mechanism. So when we push to Git, we forcefully push everything and never look back. We use the same Git commands, in a script, that commitd and pushes the entire contents of the current directory to Heroku.
Lets look at those steps in detail...
Check out Mercurial and Git
Assuming your project is already in BitBucket's Mercurial and you've created a new Heroku application, you want to check out both projects into the same directory.
As both the Mercurial and Git
clone command will only clone into an empty directory, we check them out into separate directories and manually merge them. Our goal is end up with one directory that contains our project, Mercurial's
.hg directory, and Git's hidden
C:\> hg clone <hg-repo-url> hg-dir ... C:\> heroku git:clone --app <heroku-app-name> git-dir ... C:\> mv git-dir\.git hg-dir\.git 1 dir(s) moved. C:\> rmdir /S git-dir
As you can see, the project was checked out into
hg-dir, and Heroku into
git-dir. The all important
.git directory was then copied into
git-dir was deleted.
(Note that the Powershell
mv command and not
move cannot move hidden files or folders)
Make them ignore each other
They say ignorance is bliss, and it is no different for these two mortal enemies!
You need to make sure the
.git directories are ignored in the relevant systems - otherwise you'll have Mercurial files checked into your Git repo and Git files checked into your Mercurial repo! D'Oh!
.hgignore file in the root of your project and add the following lines:
syntax: glob .git
.gitignore file in the root of your project and add the following line:
Use the Mercurial repository as per normal; using commits to track your changes. Push and pull when you feel like it, and generally ignore the fact that the Git repository exists.
Deploy to Heroku
The only time you should use Git is when you want to deploy (a new version of) your application to Heroku.
Be heavy handed with Git, commit everything at once! Don't even bother with commit messages, I mean, who cares!? We're not using it for source control, we're only using it as a deploy hook for Heroku.
In fact, at Alien-Factory, our only interaction with Git is through this simple
git add -A git commit -m "Git is!" git push heroku master
To use Mercurial as your source control manager while, at the same time, deploying to Git on Heroku you need to:
- Check out Mercurial and Git into the same directory
- Make them ignore each other
- Use Mercurial as normal
- Push everything to Git to deploy