{"thread":{"id":"8673","subject":"Moving a directory with history from one repository to another while renaming","startedAt":"2007-06-21T12:37:30Z","lastAt":"2007-06-21T14:05:38Z","messageCount":4,"participants":["Andy Parkins","Jeff King","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"45489","messageId":"200706211337.32978.andyparkins@gmail.com","threadId":"8673","inReplyTo":null,"subject":"Moving a directory with history from one repository to another while renaming","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-06-21T12:37:30Z","receivedAt":"2007-06-21T12:37:30Z","isPatch":false,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"Hello,\n\nI'm sure this has come up before, and I'm sure the answer is \ngit-filter-branch.\n\nI have repositoryA, which has a subdirectory, say \"repoA_directory\", and I've \ndone some development in it.  I now wish I'd done this development in a \ndifferent repository, repositoryB and that it would have been in a different \ndirectory, \"sub/dir/repoB_directory\".\n\nWhat's the best way to do this?\n\n*** Stop press (I tried a bit harder before sending the above email) ***\n\nThis is what I did, and am reporting here for future googlers; and in case \nyou're all interested in git-filter-branch success stories (which, \nincidentally is a fabulous little tool).\n\nIn repositoryA...\n\n git-filter-branch --subdirectory-filter \"repoA_directory\" directoryonly\n\nNow, the branch \"directoryonly\" contains repoA_directory (and history) as a \nnew root commit, and as the root directory of the repository.\n\n git checkout directoryonly\n git-filter-branch --tree-filter \"mkdir -p sub/dir/repoB_directory; \\\n    mv file1 file2 file3 sub/dir/repoB_directory\" directorymoved\n\nNow, the branch \"directorymoved\" contains repoA_directory (and history) alone, \nmoved to \"sub/dir/repoB_directory\".\n\nIn repositoryB...\n\n git-fetch /path/to/repositoryA directorymoved:repoAbranch\n\nrepositoryB now contains a new, independently rooted, branch containing only \nsub/dir/repoB_directory.  We would ideally at this point just rebase that \nindependent branch to the appropriate point in the main development branch of \nrepoB, but we can't because repoAbranch doesn't share a common ancestor with \nany of the repositoryB branches.\n\nThat is to say, we have these two branches:\n\n * --- * --- * --- * --- * (master)\n\n             B --- * --- * (repoAbranch)\n\nbut we want:\n\n * --- * --- * --- * --- * (master)\n                          \\\n                           B --- * --- * (repoAbranch)\n\nFind the commit hash of the first commit in repoAbranch, B, and apply that one \ncommit as a patch to your mainline branch (probably making a temporary branch \non your way, to preserve your current master)\n\n git checkout -b temp\n git show --pretty=email hash-of-B | git-am\n\n * --- * --- * --- * --- * (master)\n                          \\\n                           B' (temp)\n\n             B --- * --- * (repoAbranch)\n\nWe've now got a commit that will serve as a common ancestor.\n\n git-rebase --onto temp hash-of-B repoAbranch\n git-branch -D temp\n\n * --- * --- * --- * --- * (master)\n                          \\\n                           B' --- *' --- *' (repoAbranch)\n\n                           B  --- *  --- *  [orphan branch]\n\nVoila. repoAbranch is now the original repoA_directory, but stored at \nsub/dir/repoB_directory and includes the development history.\n\ngit-gc --prune will get rid of the orphan branch if you're bothered about the \nstorage.\n\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"45492","messageId":"20070621130137.GB4487@coredump.intra.peff.net","threadId":"8673","inReplyTo":"200706211337.32978.andyparkins@gmail.com","subject":"Re: Moving a directory with history from one repository to another while renaming","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-06-21T13:01:38Z","receivedAt":"2007-06-21T13:01:38Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Jun 21, 2007 at 01:37:30PM +0100, Andy Parkins wrote:\n\n>  git checkout directoryonly\n>  git-filter-branch --tree-filter \"mkdir -p sub/dir/repoB_directory; \\\n>     mv file1 file2 file3 sub/dir/repoB_directory\" directorymoved\n\nYou can do this much more efficiently by just operating on the index.\nSomething like:\n\ngit-filter-branch --index-filter \\\n 'git-ls-files -s | sed -n 's/change/paths/p' | git-update-index --index-info' \\\n directorymoved\n\n-Peff\n"},{"id":"45499","messageId":"200706211457.29030.andyparkins@gmail.com","threadId":"8673","inReplyTo":"20070621130137.GB4487@coredump.intra.peff.net","subject":"Re: Moving a directory with history from one repository to another while renaming","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-06-21T13:57:28Z","receivedAt":"2007-06-21T13:57:28Z","isPatch":false,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Thursday 2007 June 21, Jeff King wrote:\n\n> You can do this much more efficiently by just operating on the index.\n> Something like:\n>\n> git-filter-branch --index-filter \\\n>  'git-ls-files -s | sed -n 's/change/paths/p' | git-update-index\n> --index-info' \\ directorymoved\n\n:-D  Even better.  I am definitely in the \"fan of git-filter-branch\" camp.\n\nThanks for sharing that line; I've actually found it instructive for more than \njust git-filter-branch.  I definitely hadn't appreciated the fact that the \nindex can be so easily manipulated.\n\n\n\nAndy\n-- \nDr Andy Parkins, M Eng (hons), MIET\nandyparkins@gmail.com\n"},{"id":"45501","messageId":"Pine.LNX.4.64.0706211504060.4059@racer.site","threadId":"8673","inReplyTo":"200706211457.29030.andyparkins@gmail.com","subject":"Re: Moving a directory with history from one repository to another while renaming","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-06-21T14:05:38Z","receivedAt":"2007-06-21T14:05:38Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 21 Jun 2007, Andy Parkins wrote:\n\n> On Thursday 2007 June 21, Jeff King wrote:\n> \n> > You can do this much more efficiently by just operating on the index.\n> > Something like:\n> >\n> > git-filter-branch --index-filter \\\n> >  'git-ls-files -s | sed -n 's/change/paths/p' | git-update-index\n> > --index-info' \\ directorymoved\n> \n> :-D  Even better.  I am definitely in the \"fan of git-filter-branch\" camp.\n> \n> Thanks for sharing that line; I've actually found it instructive for more than \n> just git-filter-branch.  I definitely hadn't appreciated the fact that the \n> index can be so easily manipulated.\n\nYou have to adapt the line minimally: As is, it will possibly catch the \nwrong names, and it does not _move_ the directory, but rather _copy_ it.\n\nSo I think something like\n\ngit-ls-files -s | sed \"s-\\t-&newsubdir/-\" |\n  GIT_INDEX_FILE=\"$GIT_INDEX_FILE\".new git-update-index --index-info &&\nmv \"$GIT_INDEX_FILE\".new \"$GIT_INDEX_FILE\"\n\nis needed.\n\nCiao,\nDscho\n"}]}