git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Moving a directory with history from one repository to another while renaming

From
APAndy Parkins <andyparkins@gmail.com>
Date
Jun 21, 2007, 12:37 UTC
Message-ID
<200706211337.32978.andyparkins@gmail.com>
Hello,

I'm sure this has come up before, and I'm sure the answer is git-filter-branch.

I have repositoryA, which has a subdirectory, say "repoA_directory", and I've done some development in it. I now wish I'd done this development in a different repository, repositoryB and that it would have been in a different directory, "sub/dir/repoB_directory".

What's the best way to do this?
*** Stop press (I tried a bit harder before sending the above email) ***

This is what I did, and am reporting here for future googlers; and in case you're all interested in git-filter-branch success stories (which, incidentally is a fabulous little tool).

In repositoryA...
 git-filter-branch --subdirectory-filter "repoA_directory" directoryonly

Now, the branch "directoryonly" contains repoA_directory (and history) as a new root commit, and as the root directory of the repository.

 git checkout directoryonly
 git-filter-branch --tree-filter "mkdir -p sub/dir/repoB_directory; \
    mv file1 file2 file3 sub/dir/repoB_directory" directorymoved

Now, the branch "directorymoved" contains repoA_directory (and history) alone, moved to "sub/dir/repoB_directory".

In repositoryB...
 git-fetch /path/to/repositoryA directorymoved:repoAbranch

repositoryB now contains a new, independently rooted, branch containing only sub/dir/repoB_directory. We would ideally at this point just rebase that independent branch to the appropriate point in the main development branch of repoB, but we can't because repoAbranch doesn't share a common ancestor with any of the repositoryB branches.

That is to say, we have these two branches:
 * --- * --- * --- * --- * (master)
             B --- * --- * (repoAbranch)
but we want:
 * --- * --- * --- * --- * (master)
                          \
                           B --- * --- * (repoAbranch)

Find the commit hash of the first commit in repoAbranch, B, and apply that one commit as a patch to your mainline branch (probably making a temporary branch on your way, to preserve your current master)

 git checkout -b temp
 git show --pretty=email hash-of-B | git-am
 * --- * --- * --- * --- * (master)
                          \
                           B' (temp)
             B --- * --- * (repoAbranch)
We've now got a commit that will serve as a common ancestor.
 git-rebase --onto temp hash-of-B repoAbranch
 git-branch -D temp
 * --- * --- * --- * --- * (master)
                          \
                           B' --- *' --- *' (repoAbranch)
                           B  --- *  --- *  [orphan branch]

Voila. repoAbranch is now the original repoA_directory, but stored at sub/dir/repoB_directory and includes the development history.

git-gc --prune will get rid of the orphan branch if you're bothered about the storage.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com
Next: Jeff King
Message 1 of 4 in “Moving a directory with history from one repository to another while renaming”
  1. Andy ParkinsJun 21, 2007
  2. Jeff KingJun 21, 2007
  3. Andy ParkinsJun 21, 2007
  4. Johannes SchindelinJun 21, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.