Skip to content

Instantly share code, notes, and snippets.

@bonovoxly
Last active December 3, 2024 10:59
Show Gist options
  • Save bonovoxly/b4f7502f2b6cdb26a779dbfb73d4d134 to your computer and use it in GitHub Desktop.
Save bonovoxly/b4f7502f2b6cdb26a779dbfb73d4d134 to your computer and use it in GitHub Desktop.
git-filter-repo
## git-filter-repo
- Stage a working area. These are somewhat throwaway directories and local git repos.
- clone both source and target repos.
```
mkdir my-working-dir
cd my-working-dir
git clone git@github.com:bonovoxly/source.git
git clone git@github.com:bonovoxly/target.git
```
### In source repo
We checkout a branch that we will filter against. We specify the path(s) that we want.
```
cd ./source
git checkout filter-source
git filter-repo --path ansible/ansible.cfg --path ansible/file.yml --path ansible/another-file.yml --refs refs/heads/filter-source --force
```
## In target repo
```
cd ../target
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
```
@jdelder
Copy link

jdelder commented Jan 4, 2023

git remote add repo-source ../testing
Just a quick question ... what is ../testing ? Did you mean ../source since that is where the clone commands on the web page put the source repo? "git clone git@github.com:bonovoxly/source.git"

@bonovoxly
Copy link
Author

ah shoot. think i had a typo. bad translation there...

that should be

git remote add repo-source ../source

@bonovoxly
Copy link
Author

@jdelder I've edited the gist to be a bit more specific. Hopefully I didn't add NEW typos 😆

@jdelder
Copy link

jdelder commented Jan 4, 2023

Cool :) You might also want to change the blog entry since that is where I found it initially.
https://blog.billyc.io/how-to-copy-one-or-more-files-from-one-git-repo-to-another-and-keep-the-git-history/
I also used your tips plus the command
git filter-repo --to-subdirectory-filter <new_directory_name>
which I found somewhere else :)
to take a couple directories from one git repo - move them all to a new directory in the filter-source then merged that into another git repo including all the commit information.
P.S. Credit to the creators of the git filter-repo python script (https://github.com/newren/git-filter-repo)

@societymartingale
Copy link

This worked perfectly for me. I was able to migrate a large number of files from one repo to another and retain the git history.

@Gamecock
Copy link

Gamecock commented Feb 23, 2024

The nice thing is, if something goes wrong, you can just checkout main, delete the branch, start all over.

This did not work for me, when I checkout out main it was empty. I had to clone again. Great gist though.

It can really be simplified when pushing to a blank repository. After the filter
git remote add origin https://
git branch -M main
git push -u origin main

@scelfo
Copy link

scelfo commented Jul 12, 2024

Thanks for publishing this! I think there's one more typo:

git checkout filter-source should be git checkout -b filter-source

@gshel
Copy link

gshel commented Aug 23, 2024

Thank you for publishing this!

I ran into some gotchas:

  1. Install git-filter-repo
  2. If you need to move files into a different directory structure or rename them, make sure to do this in a separate, isolated commit -- don't include any other changes in that commit!
  3. To view the pretty git history made possible by your gist: git log --follow $FILEPATH

#3 will allow you to see the git history of the file after it has been renamed, so long as you follow #2

@LarrxX
Copy link

LarrxX commented Dec 3, 2024

This is by far the most elegant solution I found to merge git histories. However, I am having problems with LFS files for the final git merge:

Error downloading object: XXX: Smudge error: Error downloading XXX Not Found: [404] Not Found

error: external filter 'git-lfs-filter-process' failed
fatal: XXX: smudge filter lfs failed.

Any idea how to work around that?

FYI both source.git and target.git have LFS working correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment