Skip to content

Instantly share code, notes, and snippets.

@ushkinaz
Created February 23, 2025 16:31
Show Gist options
  • Save ushkinaz/9df079770978143b8c601ce9cc907bfb to your computer and use it in GitHub Desktop.
Save ushkinaz/9df079770978143b8c601ce9cc907bfb to your computer and use it in GitHub Desktop.
GitHub Actions workflow to rewrite cherry-picked commit messages, preserving original authors and referencing the source repository.
name: Reference backported commits
on:
push:
branches:
- backport-*
pull_request:
jobs:
rewrite-messages:
runs-on: ubuntu-latest
environment: dev
env:
ORIGINAL_REPO: ${{ vars.ORIGINAL_REPO }} # Configurable repo name
steps:
- name: Checkout the current repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Ensure full commit history
- name: Checkout original repository
uses: actions/checkout@v4
with:
repository: ${{ env.ORIGINAL_REPO }}
path: original_repo
fetch-depth: 0 # Ensure full history for commit lookup
ref: main
- name: Find All New Commits
id: find_commits
run: |
BEFORE_COMMIT="${{ github.event.before }}"
# Check if BEFORE_COMMIT exists in local history
if ! git cat-file -e "$BEFORE_COMMIT^{commit}" 2>/dev/null; then
echo "WARNING: BEFORE_COMMIT ($BEFORE_COMMIT) not found locally."
echo "Fetching full history for BEFORE_COMMIT from origin..."
# Fetch full history for BEFORE_COMMIT
git fetch origin "$BEFORE_COMMIT" || true
fi
# Check again after fetch
if git cat-file -e "$BEFORE_COMMIT^{commit}" 2>/dev/null; then
echo "Successfully fetched BEFORE_COMMIT."
if git merge-base --is-ancestor "$BEFORE_COMMIT" HEAD; then
BASE_COMMIT=$BEFORE_COMMIT
echo "Detected normal push. Using BEFORE_COMMIT as BASE_COMMIT."
else
BASE_COMMIT=$(git merge-base HEAD "$BEFORE_COMMIT")
echo "Detected force push. Using nearest merge-base as BASE_COMMIT."
fi
else
echo "ERROR: BEFORE_COMMIT ($BEFORE_COMMIT) is missing even after fetch."
echo "Falling back to origin/main."
# Use a fallback base commit
BASE_COMMIT=$(git merge-base HEAD origin/main)
fi
echo "Using BASE_COMMIT: $BASE_COMMIT"
git rev-list --reverse "$BASE_COMMIT"..HEAD > new_commits.txt
- name: Process Each Commit
run: |
if [ ! -s new_commits.txt ]; then
echo "No new commits to process. Skipping."
exit 0
fi
while IFS= read -r COMMIT; do
COMMIT_MSG=$(git log -1 --format='%B' "$COMMIT")
echo "Processing commit: $COMMIT"
echo "Message: $COMMIT_MSG"
CHERRY_PICKED_COMMIT=$(echo "$COMMIT_MSG" | sed -nE 's/.*\(cherry picked from commit ([0-9a-f]+)\).*/\1/p')
if [ -n "$CHERRY_PICKED_COMMIT" ]; then
echo "Processing cherry-picked commit: $CHERRY_PICKED_COMMIT"
if git -C original_repo cat-file -e "$CHERRY_PICKED_COMMIT^{commit}" 2>/dev/null; then
echo "Commit exists in $ORIGINAL_REPO. Rewriting message and author."
ORIGINAL_AUTHOR_NAME=$(git -C original_repo log -1 --format="%an" "$CHERRY_PICKED_COMMIT")
ORIGINAL_AUTHOR_EMAIL=$(git -C original_repo log -1 --format="%ae" "$CHERRY_PICKED_COMMIT")
echo "Original Author: $ORIGINAL_AUTHOR_NAME <$ORIGINAL_AUTHOR_EMAIL>"
NEW_MSG=$(echo "$COMMIT_MSG" | sed -E "s/\(cherry picked from commit ([0-9a-f]+)\)/\(Backported from $ORIGINAL_REPO@\1\)/")
git commit --amend --author="$ORIGINAL_AUTHOR_NAME <$ORIGINAL_AUTHOR_EMAIL>" -m "$NEW_MSG" --no-edit
else
echo "Skipping: Commit $CHERRY_PICKED_COMMIT not found in $ORIGINAL_REPO."
fi
fi
done < new_commits.txt
- name: Force Push Changes
run: |
if git diff --quiet HEAD@{1} HEAD; then
echo "No commits were changed. Skipping force push."
else
echo "Commits were modified. Force pushing..."
git push origin HEAD --force
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment