> For the complete documentation index, see [llms.txt](https://docs.n8n.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.n8n.io/administer/use-source-control-and-environments/tutorial-create-environments-with-source-control.md).

# Tutorial: Create environments with source control

{% hint style="info" %}
**Feature availability**

* Available on Business and Enterprise plans.
* You must be an n8n instance owner or instance admin to enable and configure source control.
* Instance owners and instance admins can push changes to and pull changes from the connected repository.
* Project admins can push changes to the connected repository. They can't pull changes from the repository.
  {% endhint %}

This tutorial walks through the process of setting up environments end-to-end. You'll create two environments: development and production. It uses GitHub as the Git provider. The process is similar for other providers.

n8n has built its environments feature on top of Git, a version control software. You link an n8n instance to a Git branch, and use a push-pull pattern to move work between environments. You should have some understanding of environments and Git. If you need more information on these topics, refer to:

* [Environments in n8n](/administer/use-source-control-and-environments/work-with-environments.md): the purpose of environments, and how they work in n8n.
* [Git and n8n](/administer/use-source-control-and-environments/use-git-in-n8n.md): Git concepts and source control in n8n.

## Choose your source control pattern <a href="#choose-your-source-control-pattern" id="choose-your-source-control-pattern"></a>

Before setting up source control and environments, you need to plan your environments, and how they relate to Git branches. n8n supports different [Branch patterns](/administer/use-source-control-and-environments/choose-branching-patterns.md). For environments, you need to choose between two patterns: multi-instance, multi-branch, or multi-instance, single-branch. This tutorial covers both patterns.

{% hint style="info" %}
**Recommendation: don't push and pull to the same n8n instance**

You can push work from an instance to a branch, and pull to the same instance. n8n doesn't recommend this. To reduce the risk of merge conflicts and overwriting work, try to create a process where work goes in one direction: either to Git, or from Git, but not both.
{% endhint %}

### Multiple instances, multiple branches <a href="#multiple-instances-multiple-branches" id="multiple-instances-multiple-branches"></a>

![Diagram](/files/ydlzRO9CoS01Z7A4sfMS)

The advantages of this pattern are:

* An added safety layer to prevent changes getting into your production environment by mistake. You have to do a pull request in GitHub to copy work between environments.
* It supports more than two instances.

The disadvantage is more manual steps to copy work between environments.

### Multiple instances, one branch <a href="#multiple-instances-one-branch" id="multiple-instances-one-branch"></a>

![Diagram](/files/ClVjY7gGeXpOjVXUMhOy)

The advantage of this pattern is that work is instantly available to other environments when you push from one instance.

The disadvantages are:

* If you push by mistake, there is a risk the work will make it into your production instance. If you [use a GitHub Action to automate pulls](/administer/use-source-control-and-environments/tutorial-create-environments-with-source-control.md#optional-use-a-github-action-to-automate-pulls) to production, you must either use the multi-instance, multi-branch pattern, or be careful to never push work that you don't want in production.
* Pushing and pulling to the same instance can cause data loss as changes are overridden when performing these actions. You should set up processes to ensure content flows in one direction.

## Set up your repository <a href="#set-up-your-repository" id="set-up-your-repository"></a>

Once you've chosen your pattern, you need to set up your GitHub repository.

{% tabs %}
{% tab title="Multi-branch" %}

1. [Create a new repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository).
   * Make sure the repository is private, unless you want your workflows, tags, and variable and credential stubs exposed to the internet.
   * Create the new repository with a README so you can immediately create branches.
2. Create one branch named `production` and another named `development`. Refer to [Creating and deleting branches within your repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository) for guidance.
   {% endtab %}

{% tab title="Single-branch" %}
[Create a new repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository).

* Make sure the repository is private, unless you want your workflows, tags, and variable and credential stubs exposed to the internet.
* Create the new repository with a README. This creates the `main` branch, which you'll connect to.
  {% endtab %}
  {% endtabs %}

## Connect your n8n instances to your repository <a href="#connect-your-n8n-instances-to-your-repository" id="connect-your-n8n-instances-to-your-repository"></a>

Create two n8n instances, one for development, one for production.

### Configure Git in n8n <a href="#configure-git-in-n8n" id="configure-git-in-n8n"></a>

1. Go to **Settings** > **Environments**.
2. Choose your connection method:
   * **SSH**: In **Git repository URL**, enter the SSH URL for your repository (for example, `git@github.com:username/repo.git`).
   * **HTTPS**: In **Git repository URL** enter the HTTPS URL for your repository (for example, `https://github.com/username/repo.git`).
3. Configure authentication based on your connection method:
   * **For SSH**: n8n supports ED25519 and RSA public key algorithms. ED25519 is the default. Select **RSA** under **SSH Key** if your git host requires RSA. Copy the SSH key.
   * **For HTTPS**: Enter your credentials:
     * **Username**: Your Git provider username.
     * **Token**: Your Personal Access Token (PAT) from your Git provider.

### Set up a deploy key <a href="#set-up-a-deploy-key" id="set-up-a-deploy-key"></a>

Set up SSH access by creating a deploy key for the repository using the SSH key from n8n. The key must have write access. Refer to [GitHub | Managing deploy keys](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys) for guidance.

### Connect n8n and configure your instance <a href="#connect-n8n-and-configure-your-instance" id="connect-n8n-and-configure-your-instance"></a>

{% tabs %}
{% tab title="Multi-branch" %}

1. In **Settings** > **Environments** in n8n, select **Connect**. n8n connects to your Git repository.
2. Under **Instance settings**, choose which branch you want to use for the current n8n instance. Connect the production branch to the production instance, and the development branch to the development instance.
3. Production instance only: select **Protected instance** to prevent users editing workflows in this instance.
4. Select **Save settings**.
   {% endtab %}

{% tab title="Single-branch" %}

1. In **Settings** > **Environments** in n8n, select **Connect**.
2. Under **Instance settings**, select the main branch.
3. Production instance only: select **Protected instance** to prevent users editing workflows in this instance.
4. Select **Save settings**.
   {% endtab %}
   {% endtabs %}

## Push work from development <a href="#push-work-from-development" id="push-work-from-development"></a>

In your development instance, create a few workflows, tags, variables, and credentials.

To push work to Git:

1. Select **Push** <img src="/spaces/GixZThfitWP21x2gQFpD/files/AkMyGEDJRxDUF5upeaK7" alt="Push icon" data-size="line"> in the main menu.
2. In the **Commit and push changes** modal, select which workflows and data tables you want to push. You can filter by status (new, modified, deleted) and search for items. n8n automatically pushes tags, and variable and credential stubs.

   n8n pushes the current saved version, not the published version, of the workflow. You need to then separately publish versions on the remote server.
3. Enter a commit message. This should be a one sentence description of the changes you're making.
4. Select **Commit and Push**. n8n sends the work to Git, and displays a success message on completion.

## Pull work to production <a href="#pull-work-to-production" id="pull-work-to-production"></a>

Your work is now in GitHub. If you're using a multi-branch setup, it's on the development branch. If you chose the single-branch setup, it's on main.

{% tabs %}
{% tab title="Multi-branch" %}

1. In GitHub, create a pull request to merge development into production.
2. Merge the pull request.
3. In your production instance, select **Pull** <img src="/files/9Qew5PbZtnVWBXRK7F2P" alt="Pull icon" data-size="line"> in the main menu.
   {% endtab %}

{% tab title="Single-branch" %}
In your production instance, select **Pull** <img src="/files/9Qew5PbZtnVWBXRK7F2P" alt="Pull icon" data-size="line"> in the main menu.
{% endtab %}
{% endtabs %}

<details>

<summary>View screenshot</summary>

<figure><img src="/spaces/GixZThfitWP21x2gQFpD/files/pGaXXt6lrcsioDV45FXR" alt=""><figcaption><p>Pull and push buttons when menu is closed</p></figcaption></figure>

<figure><img src="/spaces/GixZThfitWP21x2gQFpD/files/EU9LjNYKiL6Hujno6kAw" alt=""><figcaption><p>Pull and push buttons when menu is open</p></figcaption></figure>

</details>

### Optional: Use a GitHub Action to automate pulls <a href="#optional-use-a-github-action-to-automate-pulls" id="optional-use-a-github-action-to-automate-pulls"></a>

If you want to avoid logging in to your production instance to pull, you can use a [GitHub Action](https://docs.github.com/en/actions/creating-actions/about-custom-actions) and the [n8n API](/connect/n8n-api.md) to automatically pull every time you push new work to your production or main branch.

A GitHub Action example:

```yaml
name: CI
on:
  # Trigger the workflow on push or pull request events for the "production" branch
  push:
    branches: [ "production" ]
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:
jobs:
  run-pull:
    runs-on: ubuntu-latest
    steps:
      - name: PULL
				# Use GitHub secrets to protect sensitive information
        run: >
          curl --location '${{ secrets.INSTANCE_URL }}/version-control/pull' --header
          'Content-Type: application/json' --header 'X-N8N-API-KEY: ${{ secrets.INSTANCE_API_KEY }}'
```

## Next steps <a href="#next-steps" id="next-steps"></a>

Learn more about:

* [Environments in n8n](/administer/use-source-control-and-environments/work-with-environments.md) and [Git and n8n](/administer/use-source-control-and-environments/use-git-in-n8n.md)
* [Source control patterns](/administer/use-source-control-and-environments/choose-branching-patterns.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.n8n.io/administer/use-source-control-and-environments/tutorial-create-environments-with-source-control.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
