# Make a duplicate flow

**URL:** <https://discourse.nodered.org/t/make-a-duplicate-flow/6996>\
**Category:** Feature Requests\
**Created:** [18 January 2019 22:15 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996 "2019-01-18T22:15:03Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Leroxy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/leroxy/32/4806_2.png) [@Leroxy](https://discourse.nodered.org/u/Leroxy)\
**Post date:** [18 January 2019 22:15 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/1 "2019-01-18T22:15:03Z")

</div>

I would like to duplicate flows as fast as I can delete them.  
And when I mess up I can just disable them again.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [18 January 2019 22:18 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/2 "2019-01-18T22:18:06Z")

</div>

click on workspace - ctrl-(or cmd)-a to select all, ctrl-c to copy - hit plus on tab bar to add new tab - ctrl-v to paste... click to fix position. Done

---

<div class="post-metadata">

**Author:** ![Leroxy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/leroxy/32/4806_2.png) [@Leroxy](https://discourse.nodered.org/u/Leroxy)\
**Post date:** [18 January 2019 22:24 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/3 "2019-01-18T22:24:39Z")

</div>

Thank you for your quickly.

Mostly the damage is all ready done realizing I was working on the orginal.

So If I do a copy of my current mistake to a new flow then trying to work my way back into the corrupt flow with ctrl-z it deletes or undo the copy I made to the new flow 😥

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [18 January 2019 22:32 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/4 "2019-01-18T22:32:32Z")

</div>

If you have only deployed once... then there is a backup hidden in your user directory.

If your flow was called `flows_fred.json` the previous version would be `.flows_fred.json.backup`

---

<div class="post-metadata">

**Author:** ![Leroxy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/leroxy/32/4806_2.png) [@Leroxy](https://discourse.nodered.org/u/Leroxy)\
**Post date:** [18 January 2019 22:38 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/5 "2019-01-18T22:38:18Z")

</div>

Well actually my node-red emails me the complete backup flows\_...json on every deploy.  
I then copy the whole contains onto clipboard and import it back deleting every flow I don't need 😃  
For now its a cat and mouse game what I should do is read back its contains determining flow or section from within the backup then importing only the selected back in.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [18 January 2019 23:30 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/6 "2019-01-18T23:30:15Z")

</div>

Have you considered using "projects" mode? It has git history of changes!

---

<div class="post-metadata">

**Author:** ![Leroxy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/leroxy/32/4806_2.png) [@Leroxy](https://discourse.nodered.org/u/Leroxy)\
**Post date:** [19 January 2019 16:20 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/7 "2019-01-19T16:20:57Z")

</div>

omgosh that looks good I am going to look into that, Thanks!

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [7 October 2025 09:31 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/8 "2025-10-07T09:31:17Z")

</div>

I've added a menu option for this, not realising that cmd-a, cmd-c, plus icon, cmd-v was a thing:

 ![Screenshot 2025-10-07 at 11.22.58](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/3/035fc563b10e023cd0f4b1ea8171869f52e8b0ef.png)

It basically follows the path as how lock-flow and disable-flow are implemented, i.e., defining an action that is called when the menu item is selected.

For the actual "work", I defined the `duplicateWorkspace` function:

```javascript
    function duplicateWorkspace(id) {
        function getFlowDataFromCurrentWorkspace(id) {
          var activeWorkspace = id || RED.workspaces.active();
          var nodes = RED.nodes.groups(activeWorkspace);

          nodes = nodes.concat(RED.nodes.junctions(activeWorkspace));
          nodes = nodes.concat(RED.nodes.filterNodes({ z: activeWorkspace }));

          RED.nodes.eachConfig(function (n) {
            if (n.z === RED.workspaces.active() && n._def.hasUsers === false) {
              // Grab any config nodes scoped to this flow that don't
              // require any flow-nodes to use them
              nodes.push(n);
            }
          });

          var parentNode = RED.nodes.workspace(
            activeWorkspace
          ) || RED.nodes.subflow(activeWorkspace);

          nodes.unshift(parentNode);

          return RED.nodes.createExportableNodeSet(nodes);
        }

        if (!id) { return; }
        RED.view.importNodes(getFlowDataFromCurrentWorkspace(id),
            {generateIds: true, addFlow: true, touchImport: true});
    }

```

that's a hack-together function that best solved the problem of copy and replacing ids for an existing flow.

Just an idea for those that might like this.

Why? Because I spend a lot of time creating small flows that I copy and then extend ...

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [8 October 2025 14:03 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/9 "2025-10-08T14:03:06Z")

</div>

This is well done, but why enable `touchImport`?

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [8 October 2025 19:15 UTC](https://discourse.nodered.org/t/make-a-duplicate-flow/6996/10 "2025-10-08T19:15:39Z")

</div>

> [@GogoVega](#):
>
> why enable `touchImport`?

what does that even do? I don't know 🙂

I admit it, I added the feature, it worked, nothing broke and I moved on! The touchImport just looks nice there at the end ....

🙂
