AutomationFlowsDevOps › Restore n8n Workflows from GitHub

Restore n8n Workflows from GitHub

Original n8n title: [ops] Restore Workflows From Github to N8n

[OPS] Restore workflows from GitHub to n8n. Uses manualTrigger, stickyNote, noOp, github. Event-driven trigger; 17 nodes.

Event trigger★★★★☆ complexity17 nodesGitHubn8n
DevOps Trigger: Event Nodes: 17 Complexity: ★★★★☆ Added:

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "uoBZx3eMvLMxlHCS",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "[OPS] Restore workflows from GitHub to n8n",
  "tags": [],
  "nodes": [
    {
      "id": "540d147a-8185-4f3e-b2f4-522a19eb6b10",
      "name": "On clicking 'execute'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -700,
        780
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "7040674c-57b4-453d-acd4-69cbeff64180",
      "name": "Globals",
      "type": "n8n-nodes-base.set",
      "position": [
        -500,
        680
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "repo.owner",
              "value": "n8n-io"
            },
            {
              "name": "repo.name",
              "value": "n8n-backups"
            },
            {
              "name": "repo.path",
              "value": "workflows/"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "2b3a2856-4024-4fb0-b068-6bace0e6592c",
      "name": "Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1140,
        600
      ],
      "parameters": {
        "color": 2,
        "width": 389.78906250000017,
        "height": 464.79920462713443,
        "content": "## Workflow - Restore Backups\nThis workflow will restore backed-up workflows from Github. \nIt is launch by testing the workflow\n\n### Setup\nOpen Globals and update the values below\n**repo.owner:** This is your Github username\n**repo.name:** This is the name of your repository\n**repo.path:** This is the folder where your workflows are saved, within the repository.\n\nIf your username was `n8n-io` and your repository was called `n8n-backups` and you wanted the workflows to go into a `workflows` folder you would set:\n\nrepo.owner - n8n-io\nrepo.name - n8n-backups\nrepo.path - workflows"
      },
      "typeVersion": 1
    },
    {
      "id": "ba2d3355-df53-43e2-a4b2-2e031b71d687",
      "name": "Workflow name already exists",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1180,
        880
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "f012be7a-fb56-4a92-b2e5-e5ec316624e8",
      "name": "If workflow already exists",
      "type": "n8n-nodes-base.if",
      "position": [
        860,
        760
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "063d51c7-0b7a-48a4-82b3-76b370fc4265",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $('Merge Github and n8n workflows - Keep only non existing workflows based on the name').item.json.name }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d1d698f2-0ccf-4865-9ecd-9e10e725d12d",
      "name": "Set n8n existing workflows names",
      "type": "n8n-nodes-base.set",
      "position": [
        320,
        880
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "6be8c184-8fb7-47a9-ad42-d0dc3db1eea4",
              "name": "name",
              "type": "string",
              "value": "={{ $json.name }}"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "d9c58650-ca2d-47c8-a887-59407fa70e1d",
      "name": "GitHub - get all files",
      "type": "n8n-nodes-base.github",
      "position": [
        -280,
        540
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{$node[\"Globals\"].json[\"repo\"][\"owner\"]}}"
        },
        "filePath": "={{$node[\"Globals\"].json[\"repo\"][\"path\"]}}",
        "resource": "file",
        "operation": "list",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{$node[\"Globals\"].json[\"repo\"][\"name\"]}}"
        }
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7bff36b1-d526-402b-bff8-7ce2af050e2d",
      "name": "n8n - get all workflows",
      "type": "n8n-nodes-base.n8n",
      "position": [
        -500,
        880
      ],
      "parameters": {
        "filters": {}
      },
      "credentials": {
        "n8nApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "277f6400-409a-4ba0-8ad7-1241768b669a",
      "name": "GitHub - get each file",
      "type": "n8n-nodes-base.github",
      "position": [
        140,
        660
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.repo.owner }}"
        },
        "filePath": "={{ $json.path }}",
        "resource": "file",
        "operation": "get",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.repo.name }}"
        },
        "asBinaryProperty": false,
        "additionalParameters": {}
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b59f5e23-729a-41fb-be4b-1aebc573393b",
      "name": "Set name and content",
      "type": "n8n-nodes-base.set",
      "position": [
        340,
        660
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "714b0cfd-9f06-4e2f-b73d-30ef39dc40e3",
              "name": "content",
              "type": "string",
              "value": "={{ $json.content.base64Decode() }}"
            },
            {
              "id": "6f48ed58-d55a-4ee4-8cf2-373941aaa341",
              "name": "name",
              "type": "string",
              "value": "={{ $json.name.replace(\".json\", \"\") }}"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "6f642a8c-9997-42b2-b9d7-3c1f02e0e26a",
      "name": "n8n - create workflow",
      "type": "n8n-nodes-base.n8n",
      "position": [
        1180,
        660
      ],
      "parameters": {
        "operation": "create",
        "workflowObject": "={{ $('Set name and content').item.json.content }}"
      },
      "credentials": {
        "n8nApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b4ce8bdb-8c76-4c10-bf48-3664ec2f924b",
      "name": "Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -360,
        340
      ],
      "parameters": {
        "color": 2,
        "width": 861.4145066375679,
        "height": 478.9952882299376,
        "content": "## Get all Github files\n1. List all the files from your repository\n2. Get each file as a JSON. \n3. The content, retrieved as base64, is converted in the \"Set Name and Content\" node\n\n\nThe \"Set Name and Content\" node creates a list of workflows with name and content, in order to compare it with the existing n8n workflows in the workspace."
      },
      "typeVersion": 1
    },
    {
      "id": "5ff560b9-8c43-401c-869f-2b4a2e13cacc",
      "name": "Merge globals and files",
      "type": "n8n-nodes-base.merge",
      "position": [
        -60,
        660
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "008d21d9-007b-44da-8d1a-bd334ba54d61",
      "name": "Merge Github and n8n workflows - Keep only non existing workflows based on the name",
      "type": "n8n-nodes-base.merge",
      "position": [
        640,
        760
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "joinMode": "keepNonMatches",
        "mergeByFields": {
          "values": [
            {
              "field1": "name",
              "field2": "name"
            }
          ]
        },
        "outputDataFrom": "input1"
      },
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "c7ffe214-1d7b-4f4f-87c1-36d9cb8e43a9",
      "name": "Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        940
      ],
      "parameters": {
        "color": 2,
        "width": 260.44696745223945,
        "height": 196.65095879641083,
        "content": "## Merge Github and n8n workflows\n\nHere, we only keep the workflows from Github that doesn't already exist in n8n workspace, based on the name"
      },
      "typeVersion": 1
    },
    {
      "id": "3d84fd1c-c49b-4db0-951a-e38d50dae47b",
      "name": "Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        720
      ],
      "parameters": {
        "color": 2,
        "width": 344.0461264465236,
        "height": 237.66186698228626,
        "content": "## Create n8n workflow\n\nCreate the n8n workflow using:\n- Content saved in Github\n- Name of the file in Github\n\n\nIf the workflow name already exist in n8n, then the workflow is not created - to avoid duplicates."
      },
      "typeVersion": 1
    },
    {
      "id": "144a0b2e-d7b2-443d-91a5-96c09ef16b8e",
      "name": "Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -280,
        980
      ],
      "parameters": {
        "color": 2,
        "width": 378.7476641422645,
        "height": 182.45487519360773,
        "content": "## Get existing n8n workflows\n\n1. Get all workflows\n2. Prepare a list of workflows in order to compare it with the workflows saved in the Github repo."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b7a0e558-1c40-4ff8-aaed-b6e3a8ab6b8c",
  "connections": {
    "Globals": {
      "main": [
        [
          {
            "node": "GitHub - get all files",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge globals and files",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Set name and content": {
      "main": [
        [
          {
            "node": "Merge Github and n8n workflows - Keep only non existing workflows based on the name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On clicking 'execute'": {
      "main": [
        [
          {
            "node": "Globals",
            "type": "main",
            "index": 0
          },
          {
            "node": "n8n - get all workflows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub - get all files": {
      "main": [
        [
          {
            "node": "Merge globals and files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub - get each file": {
      "main": [
        [
          {
            "node": "Set name and content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge globals and files": {
      "main": [
        [
          {
            "node": "GitHub - get each file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "n8n - get all workflows": {
      "main": [
        [
          {
            "node": "Set n8n existing workflows names",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If workflow already exists": {
      "main": [
        [
          {
            "node": "n8n - create workflow",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Workflow name already exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set n8n existing workflows names": {
      "main": [
        [
          {
            "node": "Merge Github and n8n workflows - Keep only non existing workflows based on the name",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Github and n8n workflows - Keep only non existing workflows based on the name": {
      "main": [
        [
          {
            "node": "If workflow already exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

How this works

Restoring n8n workflows from a GitHub repository ensures your automation library remains up to date and resilient against data loss, saving hours of manual reconfiguration after updates or incidents. This workflow is ideal for operations teams or DevOps engineers managing multiple automations across environments. The key step involves fetching workflow files from GitHub and using the n8n integration to check for and update existing ones, preventing duplicates while seamlessly importing changes.

Use this workflow after pushing updates to your GitHub repo or recovering from an n8n instance failure, especially in event-driven setups like CI/CD pipelines. Avoid it for one-off imports without version control, as it assumes a structured repository; instead, opt for n8n's built-in import feature. Common variations include adding Slack notifications for completion status or filtering specific branches for targeted restores.

About this workflow

[OPS] Restore workflows from GitHub to n8n. Uses manualTrigger, stickyNote, noOp, github. Event-driven trigger; 17 nodes.

Source: https://github.com/Zie619/n8n-workflows — original creator credit. Request a take-down →

More DevOps workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

DevOps

This template lets you selectively import n8n workflows from a GitHub repository, even when your repository uses deeply nested folder structures.

Form Trigger, GitHub, n8n +1
DevOps

Code Github. Uses manualTrigger, stickyNote, n8n, httpRequest. Event-driven trigger; 25 nodes.

n8n, HTTP Request, GitHub +1
DevOps

Code Github. Uses manualTrigger, stickyNote, n8n, httpRequest. Event-driven trigger; 23 nodes.

n8n, HTTP Request, GitHub +1
DevOps

Backup-N8N-Workflows. Uses github, n8n. Event-driven trigger; 21 nodes.

GitHub, n8n
DevOps

github. Uses github, itemLists, n8n, moveBinaryData. Event-driven trigger; 18 nodes.

GitHub, Item Lists, n8n +1