From 96be21231bf8e19017dab118cc887a0f09b055f9 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Sat, 6 Jul 2024 19:27:22 +0200 Subject: [PATCH] improve git-split.sh (multiple splits, etc...) --- scripts/git-split.sh | 97 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/scripts/git-split.sh b/scripts/git-split.sh index 5d593b7..de7f2a7 100755 --- a/scripts/git-split.sh +++ b/scripts/git-split.sh @@ -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 . +# +# SPDX-License-Identifier: GPL-3.0-or-later 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