Created
August 15, 2013 15:57
-
-
Save x3ro/6242017 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# We need the TAB character for SED (Mac OS X sed does not understand \t) | |
TAB="$(printf '\t')" | |
function abort { | |
echo "$(tput setaf 1)$1$(tput sgr0)" | |
exit 1 | |
} | |
function request_input { | |
read -p "$(tput setaf 4)$1 $(tput sgr0)" | |
} | |
function request_confirmation { | |
read -p "$(tput setaf 4)$1 (y/n) $(tput sgr0)" | |
[ "$REPLY" == "y" ] || abort "Aborted!" | |
} | |
cat << "EOF" | |
This script rewrites your entire history, moving the current repository root | |
into a subdirectory. This can be useful if you want to merge a submodule into | |
its parent repository. | |
For example, your main repository might contain a submodule at the path src/lib/, | |
containing a file called "test.c". | |
If you would merge the submodule into the parent repository without further | |
modification, all the commits to "test.c" will have the path "/test.c", whereas | |
the file now actually lives in "src/lib/test.c". | |
If you rewrite your history using this script, adding "src/lib/" to the path | |
and the merging into the parent repository, all paths will be correct. | |
NOTE: This script might complete garble your repository, so PLEASE apply this | |
only to a clone of the repository where it does not matter if the repo is destroyed. | |
EOF | |
request_confirmation "Do you want to proceed?" | |
cat << "EOF" | |
Please provide the path which should be prepended to the current root. In the | |
above example, that would be "src/lib". Please note that the path MUST NOT contain | |
a trailing slash. | |
EOF | |
request_input "Please provide the desired path (e.g. 'src/lib'):" | |
# Escape input for SED, taken from http://stackoverflow.com/a/2705678/124257 | |
TARGET_PATH=$(echo -n "$REPLY" | sed -e 's/[\/&]/\\&/g') | |
# Last confirmation | |
git ls-files -s | sed "s/${TAB}/${TAB}$TARGET_PATH\//" | |
request_confirmation "Please take a look at the printed file list. Does it look correct?" | |
# The actual processing happens here | |
CMD="git ls-files -s | sed \"s/${TAB}/${TAB}$TARGET_PATH\//\" | GIT_INDEX_FILE=\${GIT_INDEX_FILE}.new git update-index --index-info && mv \${GIT_INDEX_FILE}.new \${GIT_INDEX_FILE}" | |
git filter-branch \ | |
--index-filter "$CMD" \ | |
HEAD | |
I wanted to say thank you for this script. It saved my life.
Love the script! However there seems to be a problem with it if the history contains empty commits. I managed to solve the problem by modifying line 60 to:
CMD="git ls-files -s | sed "s/${TAB}/${TAB}$TARGET_PATH//" | GIT_INDEX_FILE=${GIT_INDEX_FILE}.new git update-index --index-info && [ ! -f ${GIT_INDEX_FILE}.new ] || mv ${GIT_INDEX_FILE}.new ${GIT_INDEX_FILE}"
thank you for this script...
Great article. Thanks for the script and thanks to @jeremysears for the updated command.
Saved my day. Thx :)
thanks for the script!
Great! Thank you
Thank you!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is awesome. Thank you! Also note that in your main article related to this, the syntax for the following command has changed:
To: