I am currently importing a cvs project into git.
After importing, i want to rewrite the history to move an existing directory into a seperate submodule.
Suppose i have a structure like this:
file1
file2
file3
dir1
dir2
library
Now i want to rewrite the history so that the directory library is always a git submodule. Say, split out specified directories into their own submodules / subprojects
This is my currently code:
File rewrite-submodule (which is called)
cd project
git filter-branch --tree-filter $PWD/../$0-tree-filter --tag-name-filter cat -- --all
File rewrite-submodule-tree-filter
#!/bin/bash
function gitCommit()
{
unset GIT_DIR
unset GIT_WORK_TREE
git add -A
if [ -n "$(git diff --cached --name-only)" ]
then
# something to commit
git commit -F $_msg
fi
}
_git_dir=$GIT_DIR
_git_work_tree=$GIT_WORK_TREE
unset GIT_DIR
unset GIT_WORK_TREE
_dir=$PWD
if [ -d "library" ]
then
_msg=$(tempfile)
git log ${GIT_COMMIT}^! --format="%B" > $_msg
git rm -r --cached lib
cd library
if [ -d ".git" ]
then
gitCommit
else
git init
gitCommit
fi
cd ..
export GIT_DIR=$_git_dir
export GIT_WORK_TREE=$_git_work_tree
git submodule add -f ./lib
fi
GIT_DIR=$_git_dir
GIT_WORK_TREE=$_git_work_tree
This code creates the .gitmodules file, but not the submodule commit entry (the line Subproject commit <sha1-hash>, output by git diff) in the main repository and the files in directory library are still versioned in the main repository and not in the subproject repository.
Thanks in advance for any hint
The .gitmodules look like this:
[submodule "library"]
path = library
url = ./library
I resolved my own question, here is the solution:
git-submodule-split library another_libraryScript
git-submodule-split:#!/bin/bash set -eu if [ $# -eq 0 ] then echo "Usage: $0 submodules-to-split" fi export _tmp=$(mktemp -d) export _libs="$@" for i in $_libs do mkdir -p $_tmp/$i done git filter-branch --commit-filter ' function gitCommit() { git add -A if [ -n "$(git diff --cached --name-only)" ] then git commit -F $_msg fi } >/dev/null # from git-filter-branch git checkout-index -f -u -a || die "Could not checkout the index" # files that $commit removed are now still in the working tree; # remove them, else they would be added again git clean -d -q -f -x _git_dir=$GIT_DIR _git_work_tree=$GIT_WORK_TREE _git_index_file=$GIT_INDEX_FILE unset GIT_DIR unset GIT_WORK_TREE unset GIT_INDEX_FILE _msg=$(tempfile) cat /dev/stdin > $_msg for i in $_libs do if [ -d "$i" ] then unset GIT_DIR unset GIT_WORK_TREE unset GIT_INDEX_FILE cd $i if [ -d ".git" ] then gitCommit else git init >/dev/null gitCommit fi cd .. rsync -a -rtu $i/.git/ $_tmp/$i/.git/ export GIT_DIR=$_git_dir export GIT_WORK_TREE=$_git_work_tree export GIT_INDEX_FILE=$_git_index_file git rm -q -r --cached $i git submodule add ./$i >/dev/null git add $i fi done rm $_msg export GIT_DIR=$_git_dir export GIT_WORK_TREE=$_git_work_tree export GIT_INDEX_FILE=$_git_index_file if [ -f ".gitmodules" ] then git add .gitmodules fi _new_rev=$(git write-tree) shift git commit-tree "$_new_rev" "$@"; ' --tag-name-filter cat -- --all for i in $_libs do if [ -d "$_tmp/$i/.git" ] then rsync -a -i -rtu $_tmp/$i/.git/ $i/.git/ cd $i git reset --hard cd .. fi done rm -r $_tmp git for-each-ref refs/original --format="%(refname)" | while read i; do git update-ref -d $i; done git reflog expire --expire=now --all git gc --aggressive --prune=now