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

4 messages, 3 authors, 2016-06-15 · open the first message on its own page

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

From: Andy Parkins <hidden>
Date: 2016-06-15 22:43:17

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

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

From: Jeff King <hidden>
Date: 2016-06-15 22:43:17

On Thu, Jun 21, 2007 at 01:37:30PM +0100, Andy Parkins wrote:
 git checkout directoryonly
 git-filter-branch --tree-filter "mkdir -p sub/dir/repoB_directory; \
    mv file1 file2 file3 sub/dir/repoB_directory" directorymoved
You can do this much more efficiently by just operating on the index.
Something like:

git-filter-branch --index-filter \
 'git-ls-files -s | sed -n 's/change/paths/p' | git-update-index --index-info' \
 directorymoved

-Peff

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

From: Andy Parkins <hidden>
Date: 2016-06-15 22:43:17

On Thursday 2007 June 21, Jeff King wrote:
You can do this much more efficiently by just operating on the index.
Something like:

git-filter-branch --index-filter \
 'git-ls-files -s | sed -n 's/change/paths/p' | git-update-index
--index-info' \ directorymoved
:-D  Even better.  I am definitely in the "fan of git-filter-branch" camp.

Thanks for sharing that line; I've actually found it instructive for more than 
just git-filter-branch.  I definitely hadn't appreciated the fact that the 
index can be so easily manipulated.



Andy
-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com

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

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:17

Hi,

On Thu, 21 Jun 2007, Andy Parkins wrote:
On Thursday 2007 June 21, Jeff King wrote:
quoted
You can do this much more efficiently by just operating on the index.
Something like:

git-filter-branch --index-filter \
 'git-ls-files -s | sed -n 's/change/paths/p' | git-update-index
--index-info' \ directorymoved
:-D  Even better.  I am definitely in the "fan of git-filter-branch" camp.

Thanks for sharing that line; I've actually found it instructive for more than 
just git-filter-branch.  I definitely hadn't appreciated the fact that the 
index can be so easily manipulated.
You have to adapt the line minimally: As is, it will possibly catch the 
wrong names, and it does not _move_ the directory, but rather _copy_ it.

So I think something like

git-ls-files -s | sed "s-\t-&newsubdir/-" |
  GIT_INDEX_FILE="$GIT_INDEX_FILE".new git-update-index --index-info &&
mv "$GIT_INDEX_FILE".new "$GIT_INDEX_FILE"

is needed.

Ciao,
Dscho
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help