Git folder relocation, part 1

Grégoire Welraeds
4 min readJun 26, 2019

How to move a folder from one git repository to another and removing that folder from the source repository.

Originally published at https://i-logs.com/

Introduction

Today, we had to move a folder from one git repository to another. We wanted to preserve history of that folder into the destination repository. We also wanted to remove that folder from the source repository.

Because git command line instructions can be really cryptic, and because there is one or two tricks to know, we are sharing our experience to complete the process.

Initial situation

In the beginning we have a repository holding the source code of a web platform and the source code of the related presentation website. As time goes by, we understood that having both projects in the same repository was far from being an ideal situation:

  • both website and the platform does not share code
  • they have different deployment processes
  • they have different lifetime between releases
  • issues pertaining to one project have no impact on the other project.

It became obvious to us that the website part should live in its own project. The ascii image below shows the initial situation. We had to move the website folder to its own git repository. The requirements were to keep the website folder history in the destination-repository and completely get rid of this folder in the source-repository.

In this post, we cover the first requirement: move the folder with history from one repository to another.

To avoid a too long article, we will cover the second requirement (removing the folder with history from the source repository) in a future post.

Moving the folder

Step 1: prepping the source repository

The first step is to get a clean copy of the repository.

To avoid commiting our changes to the source repository, let’s cut the link between the local repository and its origin:

Next, we clean up the local source repository to only keep the folder(s) we want to move:

Note: replace <folder> with the name of the folder you want to move.

This is the first trick: we are using the filter-branch git command to rewrite our repository revision history and apply a custom filter on each of these revisions. The parameter --subdirectory-filter allows us to specify the kind of filter we want to use: only keep the history which is related to the given sub-directory. The result will contain that directory (and only that) as its project root. Finally, we provide the --all shortcut to specify we want to inspect all the revision.

It is important to note that when this command completes, the whole contents of the target folder is moved to the root of the repository, as it is shown in the picture below.

Initial directory structure:

Directory structure after filter-branch:

It is now time to commit the local changes:

We don’t want to push our changes to the remote repository (we would loose all other files and folders). As a safety measure, we have remove the link between the local source repository and the remote one in a previous step. If you haven’t, please make sure to not push your changes to the remote repository!

Step 2: prepping the target repository:

First we want to create the target repository. As we are using gitlab, this is done in gitlab interface by clicking the new project button and selecting the empty repository option.

Next we clone the new remote target repository in a folder next to the local source repository folder:

Step 3: moving the folder:

To actually perform the move of the folder between the source and the destination repositories, we use the second trick of the day: connect the source repository as a remote using a local reference. Let’s use git remote to add a new remote to the local destination-repository using a local folder as the target URL!

This is magic. Now we are able:

  1. to fetch the source from the local source-repository folder and import them in the local destination-repository.
  2. create a branch with the the source-rep remote contents
  3. merge the new branch into the master branch of the local target repository

Step 4: Cleaning and pushing

We are nearly done. It is now time to clean the local branch, the local remote reference and push the local changes to the destination-repository remote:

Note: What if the target repository is not empty?

In our situation, the target repository was initially empty. We wanted the contents of the website/ folder to become the root of the destination repository.

In some case, you might want to move a folder to a repository with already existing files and folders. In that context, the easiest way is to group all the data to be moved under one single to directory:

  1. After you have successfully ran the git filter-branch command in the source repository, create a new directory
  2. move the data into the target_folder:
  3. Commit your changes but don’t push them!

Please make sure that the new directory name (target_folder in the example above) does not cause a collision with an existing directory in the destination-repository or you might be in for some trouble.

In our next article, we will cover the second requirement which is how to get rid of a folder along with its history from a git repository.

If you are here for copy/paste only:

sources:

Originally published at https://i-logs.com/

--

--

Grégoire Welraeds

Digital entrepreneur, Owner at i-Logs SPRL, love to travel, photography, music, nature and a good laugh. Brussels, BE.