37

Assume my git repository has the following structure:

/.git /Project /Project/SubProject-0 /Project/SubProject-1 /Project/SubProject-2 

and the repository has quite some commits. Now one of the subprojects (SubProject-0) grows pretty big, and I want to take SubProject-0 out and set it up as a standalone project. Is it possible to extract all the commit history involving SubProject-0 from the parent git repository and move it to a new one?

1

2 Answers 2

40

See http://git-scm.com/docs/git-filter-branch

I think you need something like

git filter-branch --subdirectory-filter Project/SubProject-0 --prune-empty -- --all 

in a clone of the repository.

Sign up to request clarification or add additional context in comments.

3 Comments

@Rio You may also want to use the --prune-empty option to expunge commits that touched only Project/SubProject-0.
This worked for me as well. But it's worth to mention that this filter-branch seems to be somehow deprecated now as it prints message: "git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as 'git filter-repo'"
Yes it's deprecated. See docs git-scm.com/docs/git-filter-branch - filter-branch has a plethora of pitfalls that can produce non-obvious manglings of the intended history rewrite (and can leave you with little time to investigate such problems since it has such abysmal performance). These safety and performance issues cannot be backward compatibly fixed and as such, its use is not recommended. Please use an alternative history filtering tool such as git filter-repo.
4

I needed to do something similar, but I wanted to essentially move a subproject from one repo to another. What I did instead was to use fetch, since it can fetch objects from any source.

So, basically, I created a new branch, deleted the unneeded stuff in that branch, then used git fetch to pull the branch from one repo to another. Once I had the objects, merge did the trick.

E.g.

On the repository that has the original stuff:

 git checkout -b temp master git rm -r Unneeded_stuff git commit -m 'pruning' 

Then you can fetch that branch from one repository into a completely different one (unrelated):

 cd /path/to/other/repository git fetch /path/to/source/repo temp:temp 

where temp:temp means "fetch temp on the source and save it as temp in here". From there you can merge the result into your master.

 git merge temp 

You can then delete the temp branches, since in the first case it isn't something you ever want to merge with the original repo, and in the second case you have merged it.

I'm sure these steps could be compressed a bit, but this set seems nice and clear.

2 Comments

Sorry to bug you about an old post, but this is answering a useful, but different question than the OP. Could you create a new q/a pair for this answer? It would make it much easier to find.
and it would be better to use the filter method to create a temporary repository including only the files you want to move and then doing the merge step off of the temporary repository as doing it this way still has the full history of the original repo (just with a delete step as the last commit).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.