Skip to content

Instantly share code, notes, and snippets.

@burbma
Last active February 20, 2025 17:18
Show Gist options
  • Save burbma/35dbe05aaf2e0cf4d0b76d6374985e39 to your computer and use it in GitHub Desktop.
Save burbma/35dbe05aaf2e0cf4d0b76d6374985e39 to your computer and use it in GitHub Desktop.
Cherry pick commits from a legacy repo into your new one where you've changed the directory structure and already made a bunch of changes. This is useful during the early stages of a cut over when you are still maintaining both repos but once you launch the new one the old one will go away.
#!/usr/bin/env bash
# Ensure your legacy repo is on a clean check out of main.
#
# First arg is path to legacy repo.
# Second arg is the arg for git rev-list.
# Third arg is the leading directory structure to match for replacement.
# Fourth arg is the directory structure to put in as a replatement.
# Note the comment below about tabs to spaces, I could've but didn't
# parameterize that with a fifth arg.
#
# Ex: bin/cherry-pick.sh ~/src/legacy-repo HEAD...2bc237f6 src src\/js\/legacy
# Pro tip: git rev-list is inclusive...exclusive.
#
# The script will pause after getting the changes from each commit. Look for
# any weirdness like patch rejects or files not found etc. If it looks weird
# you can open another shell to manually intervene and get it sorted out. Then
# you can press any key to continue and the script will git add -a and make
# the commit automatically.
#
legacy_path=${1:-~/src/legacy-repo}
commit_range=${2:-HEAD...HEAD~}
dir_match=${3:-src}
dir_replace=${4:-src\/js\/legacy}
for commit in $(cd $legacy_path && git rev-list $commit_range | tac)
do
echo $commit
for file in $(git diff-tree --no-commit-id --name-only $commit -r)
do
new=${file/#$dir_match/$dir_replace}
git show $commit --no-color -- $file | patch --ignore-whitespace $new
# This part changes tabs to spaces. Because obviously legacy uses tabs
# and the new-shiney uses spaces. You might have different file extensions
# you want to put in here.
find -E $new -type f -regex '.*.(yaml|vue|js|ts|html)' -exec bash -c 'echo "$0" && expand -t 4 "$0" > /tmp/expand.$$ && mv /tmp/expand.$$ "$0" || exit 255' {} \;
done
read -p "Make any manual interventions then press any key to continue..." -n1 -s
echo
git add -A
git commit -m "cherry-pick legacy: $(git rev-list --abbrev-commit --format=oneline --max-count=1 $commit)"
echo
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment