Multiple environments with Heroku and Git
Tags: heroku, deploy, ci, git
Published: 2018-10-25 22:14:06

---
title: Multiple environments with Heroku and Git
published: true
description: How to push your code to multiple Heroku apps that serve as different environments.
tags: heroku, deploy, ci, git
cover_image: https://thepracticaldev.s3.amazonaws.com/i/twkf2vjj2c26qgkdmpa7.png
---

I've been using [Heroku](http://heroku.com) as a dev environment to work with my team for the last few months. It was going great until last week our client asked for a live demo 😱. 
We couldn't do a demo on a dev env, mainly because we can't ask our team to stop working during the demo (and we all know dev environments are usually filled with cat pics, "tests" and "lorem ipsums"), so we decided to create a "demo" env.
I went straight to the Heroku docs to figure out how to handle multiple environments. In this post I'll try to cover everything I learned on the subject.

##Git remote
The first thing we need to understand is `git remote`.
Taken from the GitHub docs: 
> A remote URL is Git's fancy way of saying "the place where your code is stored."

You can run this command to check which remotes you have configured in your project:

```shell
git remote -v
```

In your typical project the output would be something like this:
```shell
> origin https://your-git-repo/your-git-project (fetch)
> origin https://your-git-repo/your-git-project (push)
```

👆 In this case `your-git-project` only has 1 remote configured and it's called "origin".

*(you can also check your project's remotes under `your-git-project/.git/config`)*

In case you want to dig more into it, here's the [GitHub doc about Managing remotes](https://help.github.com/categories/managing-remotes)

##Multiple remotes
So as you may have guessed, your git project can handle multiple remotes, which means you can push your code to any existent remote.

To add a new remote to your project:
```shell
git remote add remote-name https://your-git-repo/your-git-project.git
```

And to push your code to a specific remote and branch:
```shell
git push remote-name branch-name
```

#So what about Heroku?
When we create a Heroku app using the Heroku CLI, it automatically adds the remote to our new app for us. In fact, if you check the logs you'll see something like this:

```shell
> Git remote heroku added
```

Taken from Heroku's documentation:  
>When you create an application on Heroku, it associates a new Git remote, typically named Heroku, with the local Git repository for your application.  

So the Heroku CLI takes care of adding a remote called "heroku" into your git config. My recommendation would be to replace that name for something that reflects the remote's purpose more accurately, especially if you're going to use Heroku to handle more than one environment of your app.

##Update Heroku's remote name
To set up a better name for your Heroku remote, run this command:
```shell
git remote rename heroku heroku-dev
```

##Specify the remote name when creating a Heroku app
You can also define a better remote name first hand when creating the app, like this:
```shell
heroku create myAppName --remote heroku-dev
```

##Config Vars
There's one more thing. Your app needs to know to which env it's been deployed, and that's when Config Vars come in. Config variables can be accessed from our code and used to figure out which env it's in and, for example, access that particular environment's database (you don't want your dev environment making inserts into your demo database).

We can easily add a new config var from the Heroku CLI, like this:
```shell
heroku config:add ENV="dev" --remote heroku-dev
```
E.g: Here's a simplified example of how I manage different connection strings for each environment with Node.js, MongoDB and config vars: 
```javascript
// config.js
const config = {
    dev: {
        connectionString: "mongodb://my-DEV-db-connection-string"
    },
    demo: {
        connectionString: "mongodb://my-DEMO-db-connection-string"
    }
}

// app.js
const config = require('./config').get(process.env.NODE_ENV);
const mongoose = require('mongoose');
mongoose.connect(config.connectionString, { useMongoClient: true });
```

Check out the Heroku docs to learn [More about Config vars](https://devcenter.heroku.com/articles/config-vars)

#Summary
###How to create multiple environments for a new app :

1- Create a Heroku app for every environment you need, and specify a remote name for each one.
```shell
    heroku create myAppName --remote heroku-dev
    heroku create myAppName --remote heroku-demo 
```
2-  Setup a config var for each env to let your app know where is running
```shell
    heroku config:add ENV="dev" --remote heroku-dev
    heroku config:add ENV="demo" --remote heroku-demo 
```

###In case you already have your dev environment running in Heroku and want to add new envs: 

1- Rename your current Heroku remote (optional):
```shell
    git remote rename heroku heroku-dev
```
2- Create a Heroku app for the new environment, specifying a new remote name:
```shell
    heroku create myAppName --remote heroku-demo 
```
3- Setup a config var for each env to let your app know where is running:
```shell
    heroku config:add ENV="dev" --remote heroku-dev
    heroku config:add ENV="demo" --remote heroku-demo 
```

## Now push!
Now that our remotes are all setup, we can push our changes to the demo env, like so:
```shell
    git push heroku-demo master
```
Heroku will now retrieve any dependencies our project needs and build it for us so we can have our app online almost instantly.

#That's it!
Hope this helps someone, thanks for reading!