]> Untitled Git - hvutilities.git/commitdiff
gitseg: prevent new branch deletion with local commits
authorHugo Villeneuve <hugo@hugovil.com>
Wed, 1 Apr 2026 15:36:57 +0000 (11:36 -0400)
committerHugo Villeneuve <hugo@hugovil.com>
Thu, 2 Apr 2026 23:34:04 +0000 (19:34 -0400)
Signed-off-by: Hugo Villeneuve <hugo@hugovil.com>
scripts/gitseg

index fc80f5f5b088844769b1ef162d19a0ff3346df86..f42829a0ae49f4b560c023fc0b7fabb42e41fe28 100644 (file)
@@ -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