{"id":319,"date":"2026-10-13T13:51:05","date_gmt":"2026-10-13T13:51:05","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2012\/05\/16\/use-of-p4-duplicate-command\/"},"modified":"2026-10-13T13:51:05","modified_gmt":"2026-10-13T13:51:05","slug":"use-of-p4-duplicate-command","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/use-of-p4-duplicate-command\/","title":{"rendered":"How to Use `p4 duplicate` for a Perforce Branch Path Rename (Deep Rename)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">If you need to change a depot branch path in Perforce (Helix Core) without losing history, <code>p4 duplicate<\/code> is the command designed for that job. This guide is for DevOps and SCM engineers who need a practical, low-surprise workflow for a rename-style move (often called a <em>deep rename<\/em>) and safe cleanup afterward.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Originally published on 2012-05-16; fully revised and updated.<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2012\/05\/p4-duplicate-command.png\" alt=\"p4-duplicate-command\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What <code>p4 duplicate<\/code> solves<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original problem was: <em>can a branch name\/path be effectively renamed, similar to directory rename?<\/em> The practical solution is to duplicate revisions from the old depot path to a new one, then optionally remove the old path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per the command help text cited in the original post, <code>p4 duplicate<\/code> mirrors source revisions into target revisions \u201cas if they always existed,\u201d including metadata and contents.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Duplicates revision content from source path to target path.<\/li><li>Mirrors changelist number, date, attributes, and contents (as described in the original help excerpt).<\/li><li>Duplicates integration records as well.<\/li><li>Requires target revisions not to already exist.<\/li><li>Requires target files not to be opened on any client.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Deep-rename workflow<\/h2>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Identify old depot path] --> B[Choose new depot path]\n    B --> C[Run p4 duplicate]\n    C --> D[Validate files and history]\n    D --> E{Keep old path?}\n    E -- Yes --> F[Leave source path in place]\n    E -- No --> G[Run p4 obliterate -y on old path]\n    G --> H[Update team configs and automation]\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Command sequence<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1) Duplicate old branch path to new branch path<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">p4 duplicate <span class=\"hljs-comment\">\/\/depot\/Jam\/MAINds\/... \/\/depot\/Jam\/MAIN\/...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is the core rename-style step. Make sure the target path does not already contain the revisions you are creating, and that target files are not opened on any client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2) Validate the duplicated path<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">p4 files <span class=\"hljs-comment\">\/\/depot\/Jam\/MAIN\/...<\/span>\np4 filelog <span class=\"hljs-comment\">\/\/depot\/Jam\/MAIN\/...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check that files are present at the new path and that expected history\/integration lineage appears.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3) Remove the old path only if it is no longer needed<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">p4 obliterate -y <span class=\"hljs-comment\">\/\/depot\/Jam\/MAINds\/...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Warning:<\/strong> <code>obliterate<\/code> is destructive. Use it only when your retention policy, backup posture, and team process allow permanent removal.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4) Inspect built-in help for your server\/client version<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs language-bash\">p4 help duplicate<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Command comparison for rename-style branch moves<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Command<\/th><th>Primary purpose<\/th><th>How it fits this workflow<\/th><th>Risk level<\/th><\/tr><\/thead><tbody><tr><td><code>p4 duplicate<\/code><\/td><td>Create mirrored revisions at a new depot path, including metadata\/integration records (per help excerpt)<\/td><td>Main step for deep rename\/path replacement<\/td><td>Medium<\/td><\/tr><tr><td><code>p4 integrate<\/code><\/td><td>Integrate changes between branches\/paths<\/td><td>Not a direct substitute for metadata-preserving duplication<\/td><td>Low to Medium<\/td><\/tr><tr><td><code>p4 obliterate -y<\/code><\/td><td>Permanently remove files\/history at a depot path<\/td><td>Optional cleanup after successful duplication<\/td><td>High<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Original attribution: Perforce Support and community discussion thread:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"http:\/\/maillist.perforce.com\/pipermail\/perforce-user\/2010-November\/027364.html\" target=\"_blank\" rel=\"noopener\">http:\/\/maillist.perforce.com\/pipermail\/perforce-user\/2010-November\/027364.html<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Run the duplicate operation in a controlled window to avoid active opens on target files.<\/li><li>Validate with <code>p4 files<\/code> and <code>p4 filelog<\/code> before deleting anything.<\/li><li>Treat <code>p4 obliterate -y<\/code> as a governed operation with explicit approval.<\/li><li>Update workspace views, CI jobs, and documentation to the new depot path immediately after cutover.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>When you need to move a Perforce branch path while preserving revision and integration history, `p4 duplicate` is the key command. This guide shows the workflow, exact commands, and cleanup considerations.<\/p>\n","protected":false},"author":1,"featured_media":3825,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[370],"tags":[333,2520,2518,1122,545,384,2521,2523,2524,2522,2519,2525,373,213,1980],"class_list":["post-319","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-perforce","tag-command","tag-copy","tag-duplicate","tag-guide","tag-how","tag-p4","tag-p4-clone","tag-p4-commands","tag-p4-commands-guide","tag-p4-copy","tag-p4-duplicate-command","tag-p4-duplicate-tutorial","tag-perforce","tag-tutorial","tag-use"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/319","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=319"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/319\/revisions"}],"predecessor-version":[{"id":79187,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/319\/revisions\/79187"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3825"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=319"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=319"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=319"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}