Skip to content

Instantly share code, notes, and snippets.

@rxgx
Forked from trongthanh/gist:2779392
Last active August 18, 2021 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rxgx/fab8369d27590515fe216b8dfedef558 to your computer and use it in GitHub Desktop.
Save rxgx/fab8369d27590515fe216b8dfedef558 to your computer and use it in GitHub Desktop.
How to move a folder from one repo to another and keep its commit history

Merge Filter Branch

Single path

Source: http://st-on-it.blogspot.com/2010/01/how-to-move-folders-between-git.html

First, I created a freshly cloned directory of the source repository to have a safe place to reset and retry if needed.

git clone git@github.com/rxgx/bathtub-pizza.git ingredient-sausage
# Cloning into 'ingredient-sausage'...
# remote: Enumerating objects: 2562, done.
cd ingredient-sausage

Next, I remove everything from the history in bathtub-pizza that does not make changes to anything in ingredients/sausage.

⚠️ You may not want to use the filter-branch command because of its "glut of gotchas". There is no undo after running this command. This may take a while if you have a large repo with a rich history so you may want to grab a snack.

git filter-branch --subdirectory-filter ingredients/sausage -- -- all

# WARNING: git-filter-branch has a glut of gotchas generating mangled history
#          rewrites.  Hit Ctrl-C before proceeding to abort, then use an
#          alternative filtering tool such as 'git filter-repo'
#          (https://github.com/newren/git-filter-repo/) instead.  See the
#          filter-branch manual page for more details; to squelch this warning,
#          set FILTER_BRANCH_SQUELCH_WARNING=1.

I now have a clean git repository that contains only data and history from the sausage ingredient's path. If I need to move several folders, I would've moved them into a single directory using the git mv command.

Finally, I need to update the remote's URL to my new repo so I do not accidently push to the original repo.

git remote set-url origin git@github.com/rxgx/ingredient-sausage.git

👍 Done

Avoiding path conflicts

You also might need to move all your content into some directory so it didn't conflict with the new repository when you merge it. Use commands like that:

mkdir $FOLDER_NEW/
git mv $FOLDER_TO_FILTER $FOLDER_NEW/

Once you've done commit your changes, but don't push!

git commit -m "Collected the data I need to move"

This is all about the source repository preparations. Now go to your destination repository

cd ../my-repo2/

And here is the trick. You need to connect your source repository as a remote using a local reference.

git remote add repo1 ../my-repo1/

After that simply fetch the remote source, create a branch and merge it with the destination repository in usual way

git fetch repo1
git branch repo1 remotes/repo1/master

git merge repo1 --allow-unrelated-histories

This is pretty much it, all your code and history were moved from one repository to another. All you need is to clean up a bit and push the changes to the server

git remote rm repo1
git branch -d repo1

git push origin master

That's all. After that you can nuke the temporary source repository.

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