how to copy one or more files from one git repo to another and keep the git history

how to copy one or more files from one git repo to another and keep the git history

Recently ran into the issue of needing to copy a file from one repo to another, while maintaining the git history of that file. Spun me for a loop. I was able to find some examples and decided to write out the process here. Here’s the gist if you want to cut through the noise.

background

The question is pretty straightfoward; how do you copy a file from one git repo to another and maintain history? Apparently it’s not that crazy. It basically consists of 3 steps:

  • In the source repo, filter all the files out of a specific branch that you DON’T want to copy to the new repo.
  • In the target repo, add the source repo as a remote.
  • In the target repo, create a branch referencing the source repo.
  • In the target repo, merge the branch!

It was suprisingly effective. Here’s the dance.

the setup

In a folder dedicated to this process, checkout brand new source and target repos (trying to stay away from the standard area where I would do my development). For instance:

mkdir my-working-dir
cd my-working-dir
git clone git@github.com:bonovoxly/source.git
git clone git@github.com:bonovoxly/target.git

This way, we’ve got a nice clean area to work, away from my normal space. No risk to the normal environment or development space.

source repo

Checkout a branch to filter against.

# in the source git repo
git checkout filter-source
git filter-repo --path ansible/k3s-deploy.yml --path ansible/file.yml --path ansible/another-file.yml --refs refs/heads/filter-source --force

This command basically filters out and deletes ALL FILES that don’t match the above paths. Your branch will now be stripped of all files that do not match that path. The nice thing is, if something goes wrong, you can just checkout main, delete the branch, start all over.

target repo

Now, to bring that branch into the target repo.

git checkout -b filter-target
git remote add repo-source ../source
git fetch repo-source
git branch branch-source remotes/repo-source/filter-source
git merge branch-source --allow-unrelated-histories

summary

And that’s it. Files from source repo are now in target repo, complete with git history.