1

I've a git repo, say repoA, with many subdirs. How can I detach one of the sub-directories, say dir1, and add it to another repo as a separate branch (with history)?

Secondly, how can I remove the history of the detached subdir from the repoA?

Sam
  • 19
  • 3
  • There's a tool called [`git-subtree`](https://github.com/apenwarr/git-subtree) that can split a subdir off from your repo. I don't know if it can remove the history of that subdir from your main repo though. If not, you can always do so with `git filter-branch`, though that command is a bit complex. – Lily Ballard Feb 29 '12 at 21:25
  • Thanks Kevin! I've detached the sub-directory already with: git filter-branch --subdirectory-filter dir1 --prune-empty That leaves me only with the dir1, now I have to add this directory to another repo, say RepoB, as a separate branch. The tricky part for me is this that how can I make the history of dir1 a part of the history of repoB, so whenever a user do a git clone of repoB, he can see the whole history of dir1 as well. When searching for a solution I came to know about 'graft' file, and git-rebase. But, as I've mentioned I am new to git, I've no idea how to use these options. – Sam Feb 29 '12 at 22:16
  • 1
    So you have a repo that contains only the history of `dir1`. The simplest thing to do is use `git fetch` to fetch this history into the repo you want to add it to, and then just `git merge` it in. – Lily Ballard Feb 29 '12 at 22:26

1 Answers1

1

First part of the question:

How can I detach one of the sub-directories, say dir1, and add it to another repo as a separate branch (with history)?

git checkout -b tempBranch
git filter-branch --subdirectory-filter dir1 --prune-empty 

In a second repository:

git remote add filtered_dir1 ../original_repo
git fetch filtered_dir1
git merge filtered_dir1/tempBranch

Second part of the question:

Secondly, how can I remove the history of the detached subdir from the repoA?

$ git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch dir1" --prune-empty

This might fail with a warning about being unable to make a backup; I'm not sure what this is about, but adding -f will force git-filter-branch to run anyway.

This will run in the current branch only. If you want to run it on all branches, append -- --all. Note the -- --all.

Some notes:

  1. When running git filter-branch, you will filter the branch you're on. (Rather obviously, if you think about it). If you're trying to extract some history to push into a second repository, you probably want to git filter-branch on a new branch, so that the original repository doesn't lose anything.

  2. This question has some useful information in it.

  3. git filter-branch --subdirectory-filter will make subdirectory the new root directory of the branch - it will move files from subdirectory to /. To fix this, there's an example at the bottom of the EXAMPLES section from man git-filter-branch:

    To move the whole tree into a subdirectory, or remove it from there:

       git filter-branch --index-filter \
               '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"' HEAD
    
Community
  • 1
  • 1
simont
  • 68,704
  • 18
  • 117
  • 136