improve git-split.sh (multiple splits, etc...)
This commit is contained in:
@@ -1,35 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Duplicate file, with history (well, sort of)
|
||||
#
|
||||
# Copy a git file, keeping history.
|
||||
# git-split.sh - duplicate GIT file, with history (well, sort of)
|
||||
# Sources:
|
||||
# https://stackoverflow.com/a/53849613/3079831
|
||||
# https://stackoverflow.com/a/75942970/3079831
|
||||
#
|
||||
# (C) Bruno Raoult ("br"), 2024
|
||||
# Licensed under the GNU General Public License v3.0 or later.
|
||||
# Some rights reserved. See COPYING.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with this
|
||||
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
|
||||
|
||||
CMDNAME=${0##*/} # script name
|
||||
|
||||
if (( $# != 2 )); then
|
||||
printf "Usage: %s original copy\n" "$CMDNAME"
|
||||
if (( $# == 0 || $# % 2 )); then
|
||||
printf "Usage: %s orig1 copy [orig2 copy2 ...]\n" "$CMDNAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
from="$1"
|
||||
to="$2"
|
||||
yes_or_no() {
|
||||
while true; do
|
||||
read -rp "$* [y/N]: " yn
|
||||
case $yn in
|
||||
[Yy])
|
||||
return 0
|
||||
;;
|
||||
[Nn]|"")
|
||||
printf "Aborted.\n"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# not reached
|
||||
}
|
||||
|
||||
# prints out and run a command.
|
||||
echorun () {
|
||||
printf ">>> %s\n" "$*"
|
||||
"$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
declare -A files
|
||||
declare -a from # to keep order
|
||||
|
||||
while (($#)); do
|
||||
if [[ ! -f "$1" ]]; then
|
||||
printf "Missing '%s'. Aborting.\n" "$1"
|
||||
exit 1
|
||||
elif [[ -f "$2" ]]; then
|
||||
printf "'%s' already exists. Aborting.\n" "$2"
|
||||
exit 1
|
||||
fi
|
||||
files["$1"]="$2"
|
||||
from+=("$1")
|
||||
shift 2
|
||||
done
|
||||
|
||||
printf "The following files will be split :\n"
|
||||
|
||||
for file in "${from[@]}"; do
|
||||
printf "%s -> %s\n" "$file" "${files[$file]}"
|
||||
done
|
||||
|
||||
yes_or_no "Proceed (y/N)? " || exit 1
|
||||
|
||||
branch="split-file"
|
||||
|
||||
printf "Dup from=[%s] to=[%s] branch=[%s]\n" "$from" "$to" "$branch"
|
||||
printf -v msg1 "Splitting '%s'" "${from[0]}"
|
||||
printf -v msg2 "Restore duplicated %s" "${from[0]}"
|
||||
if (( ${#from[@]} > 1 )); then
|
||||
msg1+=" and $(( ${#from[@]} - 1 )) others"
|
||||
msg2+=" and $(( ${#from[@]} - 1 )) others"
|
||||
|
||||
git checkout -b "$branch" # create and switch to branch
|
||||
fi
|
||||
printf "%s using branch '$branch'.\n" "$msg1"
|
||||
|
||||
git mv "$from" "$to" # make the duplicate
|
||||
git commit -m "Duplicate $from to $to"
|
||||
if git show-ref --verify --quiet "refs/heads/$branch"; then
|
||||
echorun git switch "$branch"
|
||||
echorun git merge master
|
||||
else
|
||||
echorun git switch -c "$branch"
|
||||
fi
|
||||
|
||||
git checkout HEAD~ "$from" # bring back the original
|
||||
git commit -m "Restore duplicated $from"
|
||||
for file in "${from[@]}"; do # make the duplicates
|
||||
echorun git mv "$file" "${files[$file]}"
|
||||
done
|
||||
echorun git commit -m "$msg1" # ... and commit
|
||||
|
||||
git checkout - # switch back to source branch
|
||||
git merge --no-ff "$branch" -m "Merge $branch" # merge dup into source branch
|
||||
for file in "${from[@]}"; do # bring back the original
|
||||
echorun git checkout HEAD~ "$file"
|
||||
done
|
||||
echorun git commit -m "$msg2" # ... and commit
|
||||
|
||||
echorun git checkout - # switch back to source branch
|
||||
echorun git merge --no-ff "$branch" -m "Merge $branch" # merge dup into source branch
|
||||
|
||||
exit 0
|
||||
|
Reference in New Issue
Block a user