Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move a file from one git repository to another while preserving history

I am trying to move a single file (call it foo.txt) from one repository to another (unrelated) repository, preserving its history. ebneter's question shows how to do this for a subdirectory. taw's question has some hints and suggestions, but not a step-by-step procedure to follow. jkeating's question looked promising, but didn't work for me. Google searches came up empty for this particular use case. What I am looking for is a clear sequence of commands to accomplish this.

The sequence of commands I started to follow was this:

$ git clone source-repo/ source-repo-copy $ cd source-repo-copy $ git filter-branch --tree-filter 'test ! "$@" = "foo.txt" && \   git rm --cached --ignore-unmatch $@ || true' --prune-empty 

The logic of my filter command is to git rm all files that are not foo.txt. I added the || true to the command to force it to have a zero return value to satisfy filter-branch.

My intention was to set source-repo-copy as a remote for my target repository (target-repo), and assuming git filter-branch filtered out everything but foo.txt, fetch and merge source-repo-copy into target-repo. Unfortunately, the git filter-branch command seemed to have no effect. It ran with no errors and appeared to grind through the 600+ commits in source-repo, but when it finished, the git log and files in source-repo-copy looked the same. Shouldn't all files but foo.txt be missing and all commits that didn't touch it be gone from the log?

At this point I don't know how to proceed. Any suggestions?

like image 642
Randall Cook Avatar asked May 09 '12 21:05

Randall Cook


People also ask

How do I copy files from one Github repository to another?

Navigate to the repository you just cloned. Pull in the repository's Git Large File Storage objects. Mirror-push to the new repository. Push the repository's Git Large File Storage objects to your mirror.


1 Answers

This worked for me, but with a whole directory.

As shown here

~$ cd neu ~/neu$ git filter-branch --subdirectory-filter FooBar HEAD ~/neu$ git reset --hard ~/neu$ git remote rm origin ~/neu$ rm -r .git/refs/original/ ~/neu$ git reflog expire --expire=now --all ~/neu$ git gc --aggressive ~/neu$ git prune ~/neu$ git remote add origin git://github.com/FooBar/neu.git 

EDIT: For a single file:

Filter the directory first:

 git filter-branch --prune-empty --subdirectory-filter myDirectory -- --all 

Filter the single file:

 git filter-branch -f --prune-empty --index-filter "git rm --cached --ignore-unmatch $(git ls-files | grep -v 'keepthisfile.txt')" 

Do some cleanup:

 git reset --hard  git gc --aggressive  git prune 

This should do it.

like image 84
blang Avatar answered Sep 21 '22 04:09

blang