We had a particular subdirectory of a repository (repoA) that really belonged in repoB. The goal is to transfer all files and history from repoA to repoB, permanently.
Thanks to Nikolai in this blog post, the move isn't too bad. I'm not going to repeat his instructions. Instead, here are three tricks we learned today:
git filter-branch --subdirectory-filter dirName -- --all
This throws away everything in a repository except what's in dirName, making dirName the new root. The "-- --all" part tells it to keep the history, but it only keeps the portion of the history relative to this directory name.
However, the experts report that I could have skipped some later steps if I had instead removed the other directories:
git filter-branch --tree-filter 'rm -rf unwanted_folder/' --prune-empty -- --all
Merging two repositories together means creating a new remote in the destination repo that points to the source repo. Fetch from it and then merge its branch into the current branch in your destination repo. The fetch and merge are very standard git.
git merge --no-commit sourceRepo/master
The new (to me) trick here is --no-commit; it lets you see and alter the results of the merge before committing.
Finally, all this merging was fine, but it required moving the newly-imported files into a directory. Once they were moved, a "git log fileName" only showed the move in the commit history. Argh! The whole point of this operation was to retain the history.
git log --follow fileName
Here's a trick useful all over the place. Telling git log to follow the rename gives the full commit history of the file, before and including the move.
Thanks to Erik Jacobsen, Mike Bishop, and Jay Harris for this info.