From 4cf162a88c8f9fb78d15d7914679f5ab20b51360 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Wed, 1 Apr 2026 11:36:57 -0400 Subject: [PATCH] gitseg: prevent new branch deletion with local commits Signed-off-by: Hugo Villeneuve --- scripts/gitseg | 79 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/scripts/gitseg b/scripts/gitseg index fc80f5f..f42829a 100644 --- a/scripts/gitseg +++ b/scripts/gitseg @@ -9,6 +9,7 @@ PROG_PATH=$(dirname ${PROG_NAME}) source ${PROG_PATH}/hvutilities.sh GITSEG_TEMP_BRANCH="gitseg-rebase" +GITSEG_DB=.gitseg-db catch() { @@ -38,6 +39,8 @@ force_push="0" orig_branch="" remote="" +touch ${GITSEG_DB} + print_usage() { echo "${PROG_NAME} -- Build branch from multiple git segments (branches)" @@ -63,6 +66,69 @@ gitseg_label() git commit --allow-empty -m "segment ${orig_branch}" } +# Global hash variables +hash_branch="" +hash_head="" + +# Arg1: optional branch +gitseg_hash_get() +{ + if [ ${#} -eq 0 ]; then + hash_branch="$(git branch --show-current)" + else + hash_branch="${1}" + fi + + hash_head="$(git rev-list -n 1 ${hash_branch})" + + if [ "${hash_head}" = "" ]; then + log_err "Unable to get HEAD revision SHA" + exit 1 + fi + + log_dbg "Latest hash for ${hash_branch}: ${hash_head}" +} + +# Git hashes characters: +# SHA-1: 7 to 40 +# SHA-256: 64 + +gitseg_record_hash() +{ + gitseg_hash_get + + if [ "${hash_branch}" = "${GITSEG_TEMP_BRANCH}" ]; then + # Do not record hash for temporary gitseg branch: + return 0 + fi + + # Try to replace existing value: + sed -e "s@^\(${hash_branch}:\) [0-9a-f]\{7,64\}\$@\1 ${hash_head}@" \ + -i ${GITSEG_DB} + + # If replacement failed, assume variable was absent and so add it: + if ! grep -q "^${hash_branch}: " ${GITSEG_DB}; then + echo "${hash_branch}: ${hash_head}" >> ${GITSEG_DB} + fi +} + +gitseg_compare_hash() +{ + gitseg_hash_get ${*} + + db_hash_head=$(cat ${GITSEG_DB} | grep "^${hash_branch}: [0-9a-f]\{7,64\}\$" | awk '{print $2}') + + log_dbg "Recorded hash for ${hash_branch}: ${db_hash_head}" + + if [ "${db_hash_head}" = "" ]; then + log_dbg "hash compare: no records (ok)" + return + elif [ "${db_hash_head}" != "${hash_head}" ]; then + log_err "error: local commits detected, cannot delete branch ${hash_branch}" + exit 1 + fi +} + # Arg1: source branch # Arg2: destination branch gitseg_new() @@ -75,8 +141,13 @@ gitseg_new() exit 1 fi - # If dest branch exits, delete it: + # Check if dest branch exits: if git branch | grep -q -e "${dest_branch}$"; then + # Check if it has local commits before deleting it: + if [ "${cmd}" != "rebase" ]; then + gitseg_compare_hash ${dest_branch} + fi + git branch ${Q} -D ${dest_branch} 1>/dev/null fi @@ -105,6 +176,8 @@ gitseg_new() git branch ${Q} -u ${remote}/${dest_branch} fi fi + + gitseg_record_hash } # Arg1: segment name @@ -168,6 +241,8 @@ gitseg_rebase() if [ "${force_push}" -eq 1 ]; then git push -f fi + + gitseg_record_hash } gitseg_stack() @@ -189,6 +264,8 @@ gitseg_stack() if [ "${force_push}" -eq 1 ]; then git push -f fi + + gitseg_record_hash } while getopts "dhpr:" flag ;do -- 2.47.3