{"id":1469,"date":"2023-05-22T14:57:13","date_gmt":"2023-05-22T09:27:13","guid":{"rendered":"https:\/\/mutesoft.com\/spaces\/software\/?p=1469"},"modified":"2023-05-23T17:46:28","modified_gmt":"2023-05-23T12:16:28","slug":"git-move-a-folder-from-one-repository-to-another-without-losing-git-history","status":"publish","type":"post","link":"https:\/\/mutesoft.com\/spaces\/software\/git-move-a-folder-from-one-repository-to-another-without-losing-git-history.html","title":{"rendered":"Git: Move a Folder From One Repository to Another Without Losing Git History"},"content":{"rendered":"\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos-1024x576.jpg\" alt=\"Move folder from one repo to another\" class=\"wp-image-1485\" srcset=\"https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos-1024x576.jpg 1024w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos-300x169.jpg 300w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos-768x432.jpg 768w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos-500x281.jpg 500w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos-800x450.jpg 800w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2023\/05\/Move-Folder-Between-Repos.jpg 1280w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In one of my projects, initially, we added the data collector module to the primary repository that contains the source code of the main app. Yes, that was a mistake, we realized later. After a few weeks of development, the data collector module grew in size and the complexity increased when we added multiple sources for data collection. Hence, we decided to move the data collector module to its own repository. In the beginning, we thought we could just cut and paste the top-level folder of the data collector module to the new repository. This sounds very simple, right? But, wait, what about the history of changes in the data-collector module? If we cut and paste the folder, we&#8217;ll completely lose the commit history. Wouldn&#8217;t it be great if we can move a folder (with sub-folders and files) of the data collector module to the new repository along with the full revision history?<\/p>\n\n\n\n<p>Git commit history is extremely useful. It serves as additional documentation of code with context. This article presents a step-by-step guide to move a folder from one Git repository to another with full revision history intact.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Move Folder From One Git Repository to Another With Revision History<\/h2>\n\n\n\n<p>Let us designate the main app repository as <code>source<\/code> and the data collector repository as <code>target<\/code>. The target repository may already exist or it can be a brand new repository. The guide remains applicable in both scenarios of the target repository. Let us designate the folder that we are going to move as <code>folder-to-move<\/code>. Here are the steps:<\/p>\n\n\n\n<p><strong>Step 1:<\/strong> In a temporary directory, clone the source repository<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git clone &lt;repo_url>\/&lt;source>.git\ncd &lt;source><\/pre>\n\n\n\n<p><strong>Step 2:<\/strong> Remove the link to the remote repository<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git remote rm origin<\/pre>\n\n\n\n<p><strong>Step 3:<\/strong> Remove files history, except for the folder we are going to move. After this step, only the content of the <code>folder-to-move<\/code> folder will be available in the root directory.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git filter-branch --subdirectory-filter &lt;folder-to-move> -- --all<\/pre>\n\n\n\n<p><strong>Step 4:<\/strong> Clean unwanted stuff<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git reset --hard\ngit gc --aggressive \ngit prune\ngit clean -fd<\/pre>\n\n\n\n<p><strong>Step 5 (Optional)<\/strong>: Move files and folders to a new parent folder and commit<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Move all files and folders to a new parent folder\nmkdir &lt;parent_folder_name>\nmv * &lt;parent_folder_name>\n\n# Commit, but do not push\ngit add .\ngit commit -m \"Move files to a directory\"<\/pre>\n\n\n\n<p><strong>Step 6:<\/strong> In the same temporary directory, clone the target repository<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git clone &lt;repo_url>\/&lt;target>.git\ncd &lt;target><\/pre>\n\n\n\n<p><strong>Step 7:<\/strong> Add a local remote to the <code>source<\/code> repository cloned before with a name (e.g. <code>source<\/code>). The first parameter is the name of the remote and the second parameter is the relative path to the source repository.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Command: git remote add name url\ngit remote add &lt;source> ..\/&lt;source><\/pre>\n\n\n\n<p><strong>Step 8:<\/strong> Pull files and history from <code>source<\/code> into the <code>target<\/code>. Please use the remote name used in Step 7.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git pull &lt;source> master --allow-unrelated-histories<\/pre>\n\n\n\n<p><strong>Step 9:<\/strong> Remove the local remote added in Step 7<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git remote rm &lt;source><\/pre>\n\n\n\n<p><strong>Step 10:<\/strong> Commit changes in the <code>target<\/code> repository and push<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">git commit -m \"Move folder\"\ngit push<\/pre>\n\n\n\n<p>Finally, delete both the cloned repositories from the temporary directory. After completing the above steps, files in the <code>folder-to-move<\/code> folder of the <code>source<\/code> repository will be available in the <code>target<\/code> repository with the revision history preserved.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Git commit history is extremely useful. It serves as additional documentation of code with context. This article presents a step-by-step guide to move a folder from one Git repository to another with full revision history intact.<\/p>\n","protected":false},"author":2,"featured_media":1485,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"none","_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","_vp_format_video_url":"","_vp_image_focal_point":[],"footnotes":""},"categories":[6,32],"tags":[41,31,36],"class_list":["post-1469","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming","category-tools","tag-command-line","tag-git","tag-tools"],"_links":{"self":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts\/1469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/comments?post=1469"}],"version-history":[{"count":16,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts\/1469\/revisions"}],"predecessor-version":[{"id":1491,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts\/1469\/revisions\/1491"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/media\/1485"}],"wp:attachment":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/media?parent=1469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/categories?post=1469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/tags?post=1469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}