carlspring
carlspring

Reputation: 32567

Moving multiple directories from one git project to another, preserving their history

I would like to move several directories from one git project into another one preserving their histories. The problem is, all the examples I'm seeing seem to be showing how to do extract a directory into it's own git project, preserving the history using git filter-branch. Is it possible to move these directories from one repository to another, keeping their history, if the destination repository already has other versioned files (not conflicting with the ones to be moved in any way)...?

Could somebody please show me an example of how to do this? Thanks!

Upvotes: 7

Views: 2750

Answers (2)

TamaMcGlinn
TamaMcGlinn

Reputation: 3238

You can do this with git subtree split and git subtree add/merge. Say your source repository is at ~/source and you want to move ~/source/subdir into ~/target at some (possibly the same) location in that git repository:

cd ~/source
git subtree split -P subdir -b split/subdir
cd ~/target
git remote add source ../source
git fetch source split/subdir
git subtree add source/split/subdir -P new_subdir

Later on, if the source has updated stuff you can do the exact same steps again except the final step, which becomes git subtree merge rather than git subtree add (with the same parameters).

The split and add/merge command don't need to be used together. You can merge in a whole repository that wasn't first split, and you can also just take the split branch and turn it into a repository, by cloning from that branch:

cd ~
git clone source/ -b split/subdir subdir
cd subdir
g remote add [email protected]/Me/MyNewProject
etc.

Upvotes: 0

carlspring
carlspring

Reputation: 32567

Answering my own question with this little script I knocked up in bash (make sure you read it first and have backed up your files):

#!/bin/bash

gitURL=$1
project=$2
srcProjectBaseDir=$3
destProjectBaseDir=$4

# Remove stale checkouts in order to do a clean clone
rm -rf ${srcProjectBaseDir}

git clone --no-hardlinks $gitURL ${srcProjectBaseDir}
cd ${srcProjectBaseDir}
git remote rm origin

# These make sure your extracted module is called as the directory's name.
# If this is of no interest to you, comment out these three lines and you
# should be alright.
mkdir temp
git add temp
git mv ${project}/ temp/

git commit -m "Refactoring: Isolated files for filter-branch."

git filter-branch --subdirectory-filter temp HEAD

git add .
git commit -m "Refactoring: Filter branched."


if [ ! -d ${destProjectBaseDir} ]; then
    mkdir ${destProjectBaseDir}
    cd ${destProjectBaseDir}
        git init
    cd ..
fi

cd ${destProjectBaseDir}
git remote add repositoryAbranch ${srcProjectBaseDir}
git pull repositoryAbranch master
git remote rm repositoryAbranch

This script is based on most of the instructions seen here (with a few additions).

Upvotes: 1

Related Questions