Skip to content
32 changes: 28 additions & 4 deletions update-pr-stack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ check_env_var() {
is_base_ancestor() {
local BRANCH="$1"
local BASE="$2"
git merge-base --is-ancestor "origin/$BASE" "origin/$BRANCH"
git merge-base --is-ancestor "$BASE" "$BRANCH"
}

# Check if a branch already has the squash commit merged (squash-merge mode only)
Expand All @@ -46,7 +46,23 @@ has_squash_commit() {
local BRANCH="$1"
local BASE="$2"
is_base_ancestor "$BRANCH" "$BASE" \
&& git merge-base --is-ancestor SQUASH_COMMIT "origin/$BRANCH"
&& git merge-base --is-ancestor SQUASH_COMMIT "$BRANCH"
}

ensure_local_branch() {
local BRANCH="$1"
log_cmd git branch -f "$BRANCH" "origin/$BRANCH"
}

UPDATED_BRANCHES=()
add_updated_branch() {
local BRANCH="$1"
for UPDATED in "${UPDATED_BRANCHES[@]}"; do
if [[ "$UPDATED" == "$BRANCH" ]]; then
return
fi
done
UPDATED_BRANCHES+=("$BRANCH")
}

format_branch_list_for_text() {
Expand All @@ -64,7 +80,10 @@ update_direct_target() {
local BRANCH="$1"
local BASE_BRANCH="$2"

if has_squash_commit "$BRANCH" "$TARGET_BRANCH"; then
ensure_local_branch "$BRANCH"
ensure_local_branch "$BASE_BRANCH"

if has_squash_commit "$BRANCH" "$BASE_BRANCH"; then
echo "✓ $BRANCH already up-to-date; skipping"
return
fi
Expand Down Expand Up @@ -115,6 +134,7 @@ update_direct_target() {
COMMIT_MSG="Merge updates from $BASE_BRANCH and squash commit"
CUSTOM_COMMIT=$(log_cmd git commit-tree MERGE_RESULT -p BEFORE_MERGE -p "origin/$MERGED_BRANCH" -p SQUASH_COMMIT -m "$COMMIT_MSG")
log_cmd git reset --hard "$CUSTOM_COMMIT"
add_updated_branch "$BRANCH"
fi
}

Expand All @@ -125,6 +145,9 @@ update_indirect_target() {
# For indirect targets, we only need to check if the parent is already
# an ancestor. If so, the branch already has all updates from the parent.
# (No SQUASH_COMMIT check needed - that's only for direct targets)
ensure_local_branch "$BRANCH"
ensure_local_branch "$BASE_BRANCH"

if is_base_ancestor "$BRANCH" "$BASE_BRANCH"; then
echo "✓ $BRANCH already up-to-date with $BASE_BRANCH; skipping"
return
Expand All @@ -133,6 +156,7 @@ update_indirect_target() {
echo "Updating indirect target $BRANCH (based on $BASE_BRANCH)"
log_cmd git checkout "$BRANCH"
log_cmd git merge --no-edit "$BASE_BRANCH"
add_updated_branch "$BRANCH"
}

ALL_CHILDREN=()
Expand Down Expand Up @@ -245,7 +269,7 @@ main() {
done

# Push all updated branches and delete the merged branch
log_cmd git push origin ":$MERGED_BRANCH" "${INITIAL_TARGETS[@]}" "${ALL_CHILDREN[@]}"
log_cmd git push origin ":$MERGED_BRANCH" "${UPDATED_BRANCHES[@]}"
}

# Only run if the script is executed directly (not sourced)
Expand Down