Git: Move files from one repo to another with history

Background

A lot of times as developers and code maintainers we need to move files/folders between code repos and most of the time we avoid exporting history because of the complexity and issues often faced during the export. However fret not anymore, I will share in this post how to easily export files with history using git command line and filter-repo command.

In the past git filter-branch used to be one of the way to achieve the export task. However due to issues associated with the history rewritings by this command, its no longer a preferred option and even the git cli prompts a warning when you use the command.

Some git users have been using patching as an alternative. However it also does not provides a seamless experience and can get complex. It might be a preferred option for git experts. However I would not suggest using it when you have a better alternative available i.e. filter-repo.

Installation

Unlike filter-branch, filter-repo is not part of git cli and needs to be installed separately.

Installation on systems using package managers can be accomplished using the available package manager and the appropriate package. However on windows the installation might be a little trickier. The installation instructions available at the project’s github repo details all the peculiarities associated with the installation.

After installing filter-repo should be available as a subcommand with git cli.

    git filter-repo <options>

Among all the available command options, the following are noteworthy for this post:

path: This is used to specify the folder/file to include with filter-repo operation.

invert-paths: Inverts the paths included i.e. the files/folders specified via path flag will now be excluded from filter-repo operation.

Walkthrough

For moving files from one repo to another please proceed along as follows:

  1. Clean the source repo

    In this step we include/exclude the files/folders and their history using the filter-repo command.

    Before starting with the cleanup step in the source repo, its a good practice to perform the cleanup in a local branch where the changes are not going to have any impact on the original repo.

    # Include file and folder from the source repo
    git filter-repo --path <include-folder> --path <include-file>
    
    # Exclude file and folder from the source repo
    git filter-repo --path <folder> --path <file> --invert-paths
    
  2. Add the source repo as a remote source for the target repo

    In this step, we move to the target repo directory and add the source repo folder as a remote origin.

    git remote add <origin-name> <source-repo-folder-path>
    
    #e.g.
    git remote add move ../repo-to-move
    
  3. Fetch and merge the changes and history from source repo In this step, we fetch changes from the remote source and merge it to the target branch.

    git fetch <origin-name>
    
    git branch <branch-name> remotes/<origin-name>/<remote-branch-name>
    
    git merge <branch-name> --allow-unrelated-histories
    
    #e.g.
    git fetch move
    
    git branch merge-remote remotes/move/migrate-remote
    
    git merge merge-remote --allow-unrelated-histories
    
  4. Cleanup

    In this step, we clean up by removing the remote source and the branch.

    git remote rm <origin-name>
    
    git branch -d <branch-name>
    
    #e.g.
    git remote rm move
    
    git branch -d merge-remote
    

That’s all folks!!