In this brief post I’ll show you how to copy one directory from one repository to another with the hisotry for it intact.
If you are unsure what you are doing then work on clean clones of your source and target repositories.
Let’s get the terminology straight now. We will be going from this state:
To this state:
Notice that the repositories are on the same directory level.
Shape your Source
cd repo-from git checkout -b source
We are checking in to a new branch because the stuff we are going to do destroys the branch you are currently on. Also, the name of the branch you are checking into will show up in the merge commit.
git filter-branch --prune-empty --subdirectory-filter tasty-directory --
Now we have the whole contents of
tasty-directory in our root directory. You could stop here and just merge te branch in if you want to move the directory to it’s own subdirectory. In our case we want to keep the structure intact so we have to reshape the history a bit to suit our needs.
git filter-branch --prune-empty --tree-filter ' if [[ ! -e tasty-directory ]]; then mkdir -p tasty-directory git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files tasty-directory fi' -f
Note that we had to force this command because
refs/original/ keeps the state of our branch from before the first
Now you should see a nice subsection of your repositories history that’s concerning only the
cd ../repo-to git remote add repo-from ../repo-from git fetch repo-from
Now we have access to our shaped branch and all of it’s history fetched. All there’s left is to merge, push and forget.
git merge repo-from/source git push git remote rm repo-from