Skip to content

Instantly share code, notes, and snippets.

@r2evans
Created March 28, 2019 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r2evans/a1683ba1048cea6a130aba56a5c9702e to your computer and use it in GitHub Desktop.
Save r2evans/a1683ba1048cea6a130aba56a5c9702e to your computer and use it in GitHub Desktop.
#!/bin/bash
# changing a single repo with subdirs like this:
#
# origrepo
# +-- subdir1
# +-- subdir2
#
# into a different/new repo with rearranged dirs (and discarded files),
# editing the full history
#
# newrepo
# +-- (all files/dirs from subdir1, now at the root)
# +-- renamed2
# +-- (all files/dirs from subdir2)
ORIGREPO=/c/path/to/origrepo
SUBDIR1=inst/shiny/SomeApp
NEWDIR1=. # no change
SUBDIR2=tests/testthat
NEWDIR2=tests
# I don't really intend for this script to be run all-at-once ...
exit -1
tmpdir1=$(mktemp -d)
tmpdir2=$(mktemp -d)
finaldir=$(mktemp -d)
## ==================================================================
## copy the old repo into two locations
## (it might be cheaper to clone once and "cp -R")
git clone ${ORIGREPO} ${tmpdir1}
git clone ${ORIGREPO} ${tmpdir2}
## ==================================================================
## prune each one
cd ${tmpdir1}
git filter-branch --force --prune-empty --tag-name-filter cat \
--subdirectory-filter ${SUBDIR1} -- --all
git gc --aggressive --prune
## we now have:
## tmprepo1
## +-- (all files/dirs from subdir1)
cd ${tmpdir2}
git filter-branch --force --prune-empty --tag-name-filter cat \
--subdirectory-filter ${SUBDIR2} -- --all
# let's say I want to remove various files by-name/by-path
git filter-branch --force --prune-empty --tag-name-filter cat \
--tree-filter 'rm -rf helper* README.md test-[0123]*' \
-- --all
git gc --aggressive --prune
## we now have:
## tmprepo2
## +-- (all files/dirs from subdir2)
## ==================================================================
## make the new "real" repo
mkdir ${finaldir}
cd ${finaldir}
git init
touch a_file_and_make_a_commit # see user's feedback
git add a_file_and_make_a_commit
git commit -am "at least one commit is needed for it to work"
## ------------------------------------------------------------------
## pattern to use for each repo# that you want copied into the root
git remote add repo1 ${tmpdir1}
git fetch repo1
git merge -s ours --no-commit --allow-unrelated-histories repo1/master
# this '-m' does a 'merge', bring files/subdirs into the root dir
git read-tree -m -u repo1/master
git commit -m "package-subdir2-to-new: import ${SUBDIR1}"
## ------------------------------------------------------------------
## pattern to use for each repo# that you want copied into a new subdir
git remote add repo2 ${tmpdir2}
git fetch repo2
git merge -s ours --no-commit --allow-unrelated-histories repo2/master
# this is where we finally move it to a new subdir in the new repo
git read-tree --prefix=${NEWDIR2} -u repo2/master
git commit -m "package-subdir2-to-new: import ${SUBDIR2}"
## ==================================================================
## optionally clean up ... PLEASE don't put "/" in these :-)
rm -rf "${tmpdir1}" "${tmpdir2}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment