From 1579c0aca8132aea0288da3ed3998de7a60febd8 Mon Sep 17 00:00:00 2001 From: Pedro Cabral Date: Fri, 17 Jul 2026 12:39:06 +0200 Subject: [PATCH] added script to propagate commits across CV branches --- build/propagate-commit-to-branches.sh | 95 +++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 build/propagate-commit-to-branches.sh diff --git a/build/propagate-commit-to-branches.sh b/build/propagate-commit-to-branches.sh new file mode 100755 index 0000000..8ddb82d --- /dev/null +++ b/build/propagate-commit-to-branches.sh @@ -0,0 +1,95 @@ +#!/bin/bash +set -euo pipefail + +# Color definitions +BOLD='\033[1m' +RED='\033[31m' +BLUE='\033[34m' +GREEN='\033[32m' +YELLOW='\033[33m' +RESET='\033[0m' + +if [[ $# -ne 1 ]]; then + echo -e "${BOLD}${RED}Error${RESET}${RED}: No commit hash provided.${RESET}" + echo "Usage: $0 " + exit 1 +fi + +COMMIT="$1" +START_BRANCH="$(git branch --show-current)" + +if [[ -z "$START_BRANCH" ]]; then + echo -e "${BOLD}${RED}Error${RESET}${RED}: Detached HEAD is not supported.${RESET}" + exit 1 +fi + +if ! git rev-parse --verify --quiet "${COMMIT}^{commit}" >/dev/null; then + echo -e "${BOLD}${RED}Error${RESET}${RED}: Commit '$COMMIT' not found.${RESET}" + exit 1 +fi + +COMMIT="$(git rev-parse --short "$COMMIT")" +PARENT_COUNT="$(git rev-list --parents -n 1 "$COMMIT" | wc -w | tr -d ' ')" + +if [[ "$PARENT_COUNT" -gt 2 ]]; then + echo -e "${BOLD}${RED}Error${RESET}${RED}: Merge commits are not supported.${RESET}" + exit 1 +fi + +if [[ -n "$(git status --porcelain)" ]]; then + echo -e "${BOLD}${RED}Error${RESET}${RED}: Working tree is not clean.${RESET}" + echo "Commit, stash, or discard local changes before replicating a commit." + exit 1 +fi + +restore_branch() { + git switch --quiet "$START_BRANCH" +} + +handle_error() { + echo -e "${BOLD}${RED}Error${RESET}${RED}: Replication failed on branch '$(git branch --show-current)'.${RESET}" + + if [[ -f "$(git rev-parse --git-path CHERRY_PICK_HEAD 2>/dev/null || true)" ]]; then + git cherry-pick --abort >/dev/null 2>&1 || true + fi + + restore_branch + exit 1 +} + +trap handle_error ERR + +echo -e "${BLUE}Replicating commit ${COMMIT} from '${START_BRANCH}' to local branches.${RESET}" + +while IFS= read -r BRANCH; do + if [[ "$BRANCH" == "$START_BRANCH" ]]; then + continue + fi + + git switch --quiet "$BRANCH" + + if git merge-base --is-ancestor "$COMMIT" HEAD; then + echo -e "${YELLOW}Skipping ${BRANCH}: commit is already present.${RESET}" + continue + fi + + echo -e "${BLUE}Cherry-picking ${COMMIT} onto ${BRANCH}.${RESET}" + if ! git cherry-pick "$COMMIT"; then + if git diff --quiet && git diff --cached --quiet; then + echo -e "${YELLOW}Skipping ${BRANCH}: commit is already applied as an equivalent patch.${RESET}" + git cherry-pick --skip + continue + fi + + false + fi + + echo -e "${GREEN}Commit successfully cherry-picked to ${BRANCH}.${RESET}" + git push + echo -e "${GREEN}Branch ${BRANCH} successfully pushed.${RESET}" + +done < <(git for-each-ref --format='%(refname:short)' refs/heads) + +restore_branch + +echo -e "${GREEN}Done. Returned to '${START_BRANCH}'.${RESET}"