Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save albertpark/3aecddc42996ed7a7f69b0f5a0d3cb33 to your computer and use it in GitHub Desktop.
Save albertpark/3aecddc42996ed7a7f69b0f5a0d3cb33 to your computer and use it in GitHub Desktop.

Extract Anything in Git Repositories - Including History

Updated May 6, 2020

I came across few files or folders I felt that was better suited in a different project; in my case in another repository. Simple way would be to just copy the files over to the new or existing repositories. This will just act as a new file with no history and perhaps someone with a sharp eye may see this as a copy pasta code from somewhere in the internet. After searching the web I found out there was an amazing method to do this with retaining the history of the file. Through some research I have come up with a simple way to accomplish this goal.

Extract any files

These are the step all you need to know how to extract files with persevering its history. First we will clone the desired repository which contains the files we want to extract:

→ $ git clone <repo-A> <temp-name-A>
→ $ cd <temp-name-A>
→ $ git remote rm origin # optional if you are paranoid

This step is optional if the files are located in a different directory other than the main directory. Using the filter-branch and --subdirectory-filter we will be filtering all the files that is located in the targeted directory:

→ $ git filter-branch --prune-empty --subdirectory-filter <target-dir> -- --all

Finally we will need to filter the files we want by using filter-branch and --index-filter. The git ls-files -z will print all the files and we will input the file names we want to keep in the <file1.ext> and <file2.ext> section. The git rm will clean up the the unwanted files from the directory:

→ $ git filter-branch -f --prune-empty --index-filter 'git ls-files -z | grep -vz "<file1.ext>\|<file2.ext>" | xargs -0 git rm --cached --ignore-unmatch'

Tip: Here is an additional step to extract these files to another repository:

→ $ cd ..
→ $ git clone <repo-Z>
→ $ cd <repo-Z>
→ $ git remote add <nick-A> ../<temp-name-A>
→ $ git pull <nick-A> master --allow-unrelated-histories # preserve all the histories
→ $ git remote rm <nick-A>
→ $ git push -u origin master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment