Skip to main content
revised solution based on more complex situation
Source Link
johnb003
  • 1.9k
  • 16
  • 30

EDIT: Is your original directory structure like this then?

/ Web/ # Mixed Some CommonLib files, Some Project1 files, Some Project2 files Other1/ # Files only found in project1 Other2/ # Files only found in project2 

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

I was assuming you had project subfolders for the following response:

First of all In the end, I recommend you keep the common lib included in your projects especially due to the divergence you spoke about, so your ideal structure should be:

# CommonRepo /  CommonLib.Data/ CommonLib.Web/ # Project1Repo / Project1.sln Project1.Data/ Project1.Web/  Project1.Other/ CommonLib/  # thisI willrecommend bethat theyou subtreedo folderwhatever forrestructuring yourneeded CommonRepo to support this in Web/a sub-directory Web CommonLib.Data/ Other CommonLib.Web/ # Project2Repo / Project2.sln Project2.Data/  Project2.Web/ CommonLib/  # thisI willrecommend bethat theyou subtreedo folderwhatever forrestructuring yourneeded CommonRepoto support this in a sub-directory WebCommonLib.Data/   CommonLib.Web/ 

Split CommonLib and create the tracking repository

# Assuming you'd want to base your CommonLib on the master branch git checkout master git subtree split --prefix=CommonLib --branch=temp-CommonLib 
  1. I recommend you clone your whole depo before starting just to be sure you don't lose anything.

    git clone <big-repo> <big-repo-clone> 
  2. Prepare the old repo

    pushd <big-repo-clone> # split for the common lib git checkout master # assuming you want your common lib at master git subtree split --prefix=Source --branch=temp-commonLib # split the projects from their respective branches git checkout <branch-for-project1> git subtree split --prefix=Source --branch=temp-project1 # split the projects from their respective branches git checkout <branch-for-project2> git subtree split --prefix=Source --branch=temp-project2 
  3. Now we need to clean out the parts of those projects that we don't want there. Since they're mixed in you can't really use sub-tree but you can filter-branch to rewrite the history without the other parts.

    # strip unrelated parts from the CommonLib git checkout temp-commonLib git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch Project1* Project2*' HEAD # strip unrelated parts from the Project1 git checkout temp-project1 git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch CommonLib* Project2*' HEAD # strip unrelated parts from the Project2 git checkout temp-project2 git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch CommonLib* Project1*' HEAD 

I think gitThe prune empty will auto switch tostrip the branch aftercommits that, so from there become empty because they only contained changes that were in the folders you could, git push to some remote, OR..removed.

cd /new/path/of/tracking/repos/CommonLib git init git pull /path/of/old/repo temp-CommonLib 

For Each Project

NowNote: All of these changes are at the /source level so that it can be the new root for each project,. You can later add your solution back in. Or you can switch to the relevant branch, split the projectuse this prune technique with clones instead of subtrees, and if needed also splitwhen you're all done you can just move all the CommonLib in that branch againcontents from '/Source' to get the changes not part of the main lib.'/'

git checkout some-branch-project git subtree split --prefix=ProjectPath --branch=temp-ProjectName git subtree split --prefix=CommonLib --branch=temp-ProjectName-CommonLib cd /new/path/of/tracking/repos/ProjectName git init git pull /path/of/old/repo temp-ProjectName git commit # now create the proper sub-tree common lib git subtree add --prefix=CommonLib /path/of/old/repo temp-ProjectName-CommonLib 

Personally, I wouldn't bother with creatingNow your is going to have extra branches of the CommonLib for each project's variationand backups in refs/original/refs/heads/<branch-name>. I'd pull fromIf during the split directly, and then later ifprocess you contribute changes fromget a project to the commonLib repofatal error with filter-branch, you can just specify that whenre-create the branch and start again, or if you're confident it didn't do anything yet you pushcan delete this backup with: git update-ref -d refs/original/refs/heads/<branch-name>.

cd /new/path/of/tracking/repos/ProjectName git subtree pull --prefix=CommonLib /new/path/of/tracking/repos/CommonLib # resolve conflicts with the base, rebase if you must, and then: git subtree push --prefix=CommonLib /new/path/of/tracking/repos/CommonLib 
  1. Now just create new repos to store the projects created from those branches

    popd # to get out of <big-repo-clone> mkdir <new-repo> pushd <new-repo> git init git pull <big-repo-clone> <name-of-branch> # like temp-project1 popd # to get out of the <new-repo> 
  2. One last thing, lets pull the CommonRepo into the projects.

    pushd <new-project-repo> git subtree add --prefix=CommonLib <new-commonlib-repo> 

You then just need to bring in the .sln files (I'll leave this last step up to you).

EDIT: Is your original directory structure like this then?

/ Web/ # Mixed Some CommonLib files, Some Project1 files, Some Project2 files Other1/ # Files only found in project1 Other2/ # Files only found in project2 

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

I was assuming you had project subfolders for the following response:

First of all, I recommend you keep the common lib included in your projects especially due to the divergence you spoke about, so your ideal structure should be:

# CommonRepo / Web/ # Project1Repo / CommonLib/ # this will be the subtree folder for your CommonRepo  Web/ Web/ Other/ # Project2Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ 

Split CommonLib and create the tracking repository

# Assuming you'd want to base your CommonLib on the master branch git checkout master git subtree split --prefix=CommonLib --branch=temp-CommonLib 

I think git will auto switch to the branch after that, so from there you could, git push to some remote, OR...

cd /new/path/of/tracking/repos/CommonLib git init git pull /path/of/old/repo temp-CommonLib 

For Each Project

Now for each project, you can switch to the relevant branch, split the project, and if needed also split the CommonLib in that branch again to get the changes not part of the main lib.

git checkout some-branch-project git subtree split --prefix=ProjectPath --branch=temp-ProjectName git subtree split --prefix=CommonLib --branch=temp-ProjectName-CommonLib cd /new/path/of/tracking/repos/ProjectName git init git pull /path/of/old/repo temp-ProjectName git commit # now create the proper sub-tree common lib git subtree add --prefix=CommonLib /path/of/old/repo temp-ProjectName-CommonLib 

Personally, I wouldn't bother with creating branches of the CommonLib for each project's variation. I'd pull from the split directly, and then later if you contribute changes from a project to the commonLib repo you can just specify that when you push:

cd /new/path/of/tracking/repos/ProjectName git subtree pull --prefix=CommonLib /new/path/of/tracking/repos/CommonLib # resolve conflicts with the base, rebase if you must, and then: git subtree push --prefix=CommonLib /new/path/of/tracking/repos/CommonLib 

In the end, I recommend you keep the common lib included in your projects especially due to the divergence you spoke about, so your ideal structure should be:

# CommonRepo /  CommonLib.Data/ CommonLib.Web/ # Project1Repo / Project1.sln Project1.Data/ Project1.Web/  Project1.Other/ CommonLib/  # I recommend that you do whatever restructuring needed to support this in a sub-directory  CommonLib.Data/  CommonLib.Web/ # Project2Repo / Project2.sln Project2.Data/  Project2.Web/ CommonLib/  # I recommend that you do whatever restructuring needed to support this in a sub-directory CommonLib.Data/   CommonLib.Web/ 
  1. I recommend you clone your whole depo before starting just to be sure you don't lose anything.

    git clone <big-repo> <big-repo-clone> 
  2. Prepare the old repo

    pushd <big-repo-clone> # split for the common lib git checkout master # assuming you want your common lib at master git subtree split --prefix=Source --branch=temp-commonLib # split the projects from their respective branches git checkout <branch-for-project1> git subtree split --prefix=Source --branch=temp-project1 # split the projects from their respective branches git checkout <branch-for-project2> git subtree split --prefix=Source --branch=temp-project2 
  3. Now we need to clean out the parts of those projects that we don't want there. Since they're mixed in you can't really use sub-tree but you can filter-branch to rewrite the history without the other parts.

    # strip unrelated parts from the CommonLib git checkout temp-commonLib git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch Project1* Project2*' HEAD # strip unrelated parts from the Project1 git checkout temp-project1 git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch CommonLib* Project2*' HEAD # strip unrelated parts from the Project2 git checkout temp-project2 git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch CommonLib* Project1*' HEAD 

The prune empty will strip the commits that become empty because they only contained changes that were in the folders you removed.

Note: All of these changes are at the /source level so that it can be the new root for each project. You can later add your solution back in. Or you can use this prune technique with clones instead of subtrees, and when you're all done you can just move all the contents from '/Source' to '/'

Now your is going to have extra branches and backups in refs/original/refs/heads/<branch-name>. If during the process you get a fatal error with filter-branch, you can re-create the branch and start again, or if you're confident it didn't do anything yet you can delete this backup with: git update-ref -d refs/original/refs/heads/<branch-name>.

  1. Now just create new repos to store the projects created from those branches

    popd # to get out of <big-repo-clone> mkdir <new-repo> pushd <new-repo> git init git pull <big-repo-clone> <name-of-branch> # like temp-project1 popd # to get out of the <new-repo> 
  2. One last thing, lets pull the CommonRepo into the projects.

    pushd <new-project-repo> git subtree add --prefix=CommonLib <new-commonlib-repo> 

You then just need to bring in the .sln files (I'll leave this last step up to you).

fixed commands that should have been pull instead of add
Source Link
johnb003
  • 1.9k
  • 16
  • 30

EDIT: Is your original directory structure like this then?

/ Web/ # Mixed Some CommonLib files, Some Project1 files, Some Project2 files Other1/ # Files only found in project1 Other2/ # Files only found in project2 

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

I was assuming you had project subfolders for the following response:

First of all, I recommend you keep the common lib included in your projects especially due to the divergence you spoke about, so your ideal structure should be:

# CommonRepo / Web/ # Project1Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ Other/ # Project2Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ 

Now to handle the splitting:

when you split, as long as you don't use different annotations or something the commit ids will be compatible and should play nicely with merge. So you can start by extracting the CommonLib by itself.

Split CommonLib and create the tracking repository

# Assuming you'd want to base your CommonLib on the master branch git checkout master git subtree split --prefix=CommonLib --branch=temp-CommonLib 

I think git will auto switch to the branch after that, so from there you could, git push to some remote, OR...

cd /new/path/of/tracking/repos/CommonLib git init git addpull /path/of/old/repo temp-CommonLib 

For Each Project

Now for each project, you can switch to the relevant branch, split the project, and if needed also split the CommonLib in that branch again to get the changes not part of the main lib.

git checkout some-branch-project git subtree split --prefix=ProjectPath --branch=temp-ProjectName git subtree split --prefix=CommonLib --branch=temp-ProjectName-CommonLib cd /new/path/of/tracking/repos/ProjectName git init git addpull /path/of/old/repo temp-ProjectName git commit # now create the proper sub-tree common lib git subtree add --prefix=CommonLib /path/of/old/repo temp-ProjectName-CommonLib 

Personally, I wouldn't bother with creating branches of the CommonLib for each project's variation. I'd pull from the split directly, and then later if you contribute changes from a project to the commonLib repo you can just specify that when you push:

cd /new/path/of/tracking/repos/ProjectName git subtree pull --prefix=CommonLib /new/path/of/tracking/repos/CommonLib # resolve conflicts with the base, rebase if you must, and then: git subtree push --prefix=CommonLib /new/path/of/tracking/repos/CommonLib 

EDIT: Is your original directory structure like this then?

/ Web/ # Mixed Some CommonLib files, Some Project1 files, Some Project2 files Other1/ # Files only found in project1 Other2/ # Files only found in project2 

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

I was assuming you had project subfolders for the following response:

First of all, I recommend you keep the common lib included in your projects especially due to the divergence you spoke about, so your ideal structure should be:

# CommonRepo / Web/ # Project1Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ Other/ # Project2Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ 

Now to handle the splitting:

when you split, as long as you don't use different annotations or something the commit ids will be compatible and should play nicely with merge. So you can start by extracting the CommonLib by itself.

Split CommonLib and create the tracking repository

# Assuming you'd want to base your CommonLib on the master branch git checkout master git subtree split --prefix=CommonLib --branch=temp-CommonLib 

I think git will auto switch to the branch after that, so from there you could, git push to some remote, OR...

cd /new/path/of/tracking/repos/CommonLib git init git add /path/of/old/repo temp-CommonLib 

For Each Project

Now for each project, you can switch to the relevant branch, split the project, and if needed also split the CommonLib in that branch again to get the changes not part of the main lib.

git checkout some-branch-project git subtree split --prefix=ProjectPath --branch=temp-ProjectName git subtree split --prefix=CommonLib --branch=temp-ProjectName-CommonLib cd /new/path/of/tracking/repos/ProjectName git init git add /path/of/old/repo temp-ProjectName git commit # now create the proper sub-tree common lib git subtree add --prefix=CommonLib /path/of/old/repo temp-ProjectName-CommonLib 

Personally, I wouldn't bother with creating branches of the CommonLib for each project's variation. I'd pull from the split directly, and then later if you contribute changes from a project to the commonLib repo you can just specify that when you push:

cd /new/path/of/tracking/repos/ProjectName git subtree pull --prefix=CommonLib /new/path/of/tracking/repos/CommonLib # resolve conflicts with the base, rebase if you must, and then: git subtree push --prefix=CommonLib /new/path/of/tracking/repos/CommonLib 

EDIT: Is your original directory structure like this then?

/ Web/ # Mixed Some CommonLib files, Some Project1 files, Some Project2 files Other1/ # Files only found in project1 Other2/ # Files only found in project2 

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

I was assuming you had project subfolders for the following response:

First of all, I recommend you keep the common lib included in your projects especially due to the divergence you spoke about, so your ideal structure should be:

# CommonRepo / Web/ # Project1Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ Other/ # Project2Repo / CommonLib/ # this will be the subtree folder for your CommonRepo Web/ Web/ 

Now to handle the splitting:

when you split, as long as you don't use different annotations or something the commit ids will be compatible and should play nicely with merge. So you can start by extracting the CommonLib by itself.

Split CommonLib and create the tracking repository

# Assuming you'd want to base your CommonLib on the master branch git checkout master git subtree split --prefix=CommonLib --branch=temp-CommonLib 

I think git will auto switch to the branch after that, so from there you could, git push to some remote, OR...

cd /new/path/of/tracking/repos/CommonLib git init git pull /path/of/old/repo temp-CommonLib 

For Each Project

Now for each project, you can switch to the relevant branch, split the project, and if needed also split the CommonLib in that branch again to get the changes not part of the main lib.

git checkout some-branch-project git subtree split --prefix=ProjectPath --branch=temp-ProjectName git subtree split --prefix=CommonLib --branch=temp-ProjectName-CommonLib cd /new/path/of/tracking/repos/ProjectName git init git pull /path/of/old/repo temp-ProjectName git commit # now create the proper sub-tree common lib git subtree add --prefix=CommonLib /path/of/old/repo temp-ProjectName-CommonLib 

Personally, I wouldn't bother with creating branches of the CommonLib for each project's variation. I'd pull from the split directly, and then later if you contribute changes from a project to the commonLib repo you can just specify that when you push:

cd /new/path/of/tracking/repos/ProjectName git subtree pull --prefix=CommonLib /new/path/of/tracking/repos/CommonLib # resolve conflicts with the base, rebase if you must, and then: git subtree push --prefix=CommonLib /new/path/of/tracking/repos/CommonLib 
added 99 characters in body
Source Link
johnb003
  • 1.9k
  • 16
  • 30

 

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

The following is being revised due to misinterpretation of the question.I was assuming you had project subfolders for the following response:


 

The following is being revised due to misinterpretation of the question.

Here's another question that's already been asked that I think answers it better: Detach (move) subdirectory into separate Git repository

I was assuming you had project subfolders for the following response:

added 354 characters in body
Source Link
johnb003
  • 1.9k
  • 16
  • 30
Loading
Source Link
johnb003
  • 1.9k
  • 16
  • 30
Loading