Skip to content

Instantly share code, notes, and snippets.

@jancbeck
Last active February 26, 2025 15:26
Show Gist options
  • Save jancbeck/9ee4ad5e3af3322175fb80804d70cfc5 to your computer and use it in GitHub Desktop.
Save jancbeck/9ee4ad5e3af3322175fb80804d70cfc5 to your computer and use it in GitHub Desktop.
Sync epic branch

Git Branch Sync

A set of scripts to keep your branches synchronized in a large monorepo development environment.

Purpose

These scripts help automate Git branch management when working with a branching strategy that requires:

  • Keeping an epic branch in sync with main
  • Ensuring feature branches include changes from their parent epic branches
  • Handling potential merge conflicts safely

Installation

  1. Clone or download these scripts into your repository's /scripts directory

  2. Make the scripts executable:

    chmod +x /path/to/scripts/branch-sync.sh
  3. Set up Git aliases for convenience:

    # Add commonly used epic branch
    git config --local alias.sync-gs '!bash $(git rev-parse --show-toplevel)/scripts/branch-sync.sh --epic gs-maker-checker/ENG-32296'
    
    # Add custom epic branch sync
    git config --local alias.sync-with '!f() { bash $(git rev-parse --show-toplevel)/scripts/branch-sync.sh --epic "$1"; }; f'

Usage

Sync with the gs-maker-checker epic branch

git sync-gs

Sync with a custom epic branch

git sync-with feature/my-epic-branch

Sync with a custom epic and main branch

bash scripts/branch-sync.sh --epic feature/my-epic-branch --main develop

How It Works

The branch sync process:

  1. Stashes any uncommitted changes to preserve your work

  2. Fetches the latest changes from the remote repository

  3. Updates the epic branch with changes from main:

    • Checks out the epic branch
    • Merges main into the epic branch
    • Pushes the updated epic branch
  4. Updates your feature branch:

    • Returns to your original branch
    • Merges the epic branch into your feature branch
    • Pushes your updated feature branch
  5. Restores your uncommitted changes

Handling Merge Conflicts

If merge conflicts occur:

  1. The script will notify you with clear instructions
  2. You'll remain in the conflicting branch to resolve issues
  3. Your original changes will be safely stashed
  4. After resolving conflicts, you can continue by running the script again

Options

The branch-sync.sh script supports the following options:

Usage: ./branch-sync.sh [options]
Options:
  -e, --epic BRANCH   Specify the epic branch name (REQUIRED)
  -m, --main BRANCH   Specify the main branch name (default: main)
  -h, --help          Show this help message

Troubleshooting

Permission Denied

If you get "permission denied" errors, make sure the scripts are executable:

chmod +x scripts/branch-sync.sh

Failed to Push

If pushing fails, the script will provide instructions. Common solutions:

  • Pull the latest changes with git pull --rebase origin <branch-name>
  • Resolve any conflicts and try again

Merge Conflicts

If merge conflicts occur:

  1. Open the conflicting files in your editor
  2. Resolve the conflicts manually
  3. Add resolved files with git add <files>
  4. Complete the merge with git commit
  5. Run the sync script again
#!/bin/bash
# Default configuration
MAIN_BRANCH="main"
EPIC_BRANCH=""
# Parse command-line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-e|--epic) EPIC_BRANCH="$2"; shift ;;
-m|--main) MAIN_BRANCH="$2"; shift ;;
-h|--help)
echo "Usage: $0 [options]"
echo "Options:"
echo " -e, --epic BRANCH Specify the epic branch name (REQUIRED)"
echo " -m, --main BRANCH Specify the main branch name (default: $MAIN_BRANCH)"
echo " -h, --help Show this help message"
exit 0
;;
*) echo "Unknown parameter: $1"; exit 1 ;;
esac
shift
done
# Check if epic branch is provided
if [ -z "$EPIC_BRANCH" ]; then
echo "Error: Epic branch parameter is required."
echo "Please specify an epic branch using -e or --epic option."
echo "Example: $0 --epic feature/my-epic-branch"
exit 1
fi
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo "${YELLOW}Starting branch sync process...${NC}"
echo "${YELLOW}Main branch: ${MAIN_BRANCH}${NC}"
echo "${YELLOW}Epic branch: ${EPIC_BRANCH}${NC}"
# Store current branch to return to it later
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
echo "${YELLOW}Current branch: ${CURRENT_BRANCH}${NC}"
# Fetch latest changes from remote
echo "${YELLOW}Fetching latest changes from remote...${NC}"
git fetch origin || { echo "${RED}Failed to fetch from remote!${NC}"; exit 1; }
# Check if we need to stash changes
if ! git diff --quiet; then
echo "${YELLOW}Stashing your local changes...${NC}"
git stash push -m "Auto-stash before syncing branches"
STASHED=true
else
STASHED=false
fi
# STEP 1: Update epic branch with main
echo ""
echo "${YELLOW}STEP 1: Updating epic branch with main${NC}"
echo "${YELLOW}Switching to epic branch ${EPIC_BRANCH}...${NC}"
git checkout $EPIC_BRANCH || {
echo "${RED}Failed to switch to epic branch!${NC}"
if [ "$STASHED" = true ]; then
echo "${YELLOW}Restoring your stashed changes...${NC}"
git stash pop
fi
git checkout $CURRENT_BRANCH
exit 1
}
echo "${YELLOW}Merging $MAIN_BRANCH into $EPIC_BRANCH...${NC}"
if ! git merge origin/$MAIN_BRANCH -m "Merge $MAIN_BRANCH into $EPIC_BRANCH"; then
echo "${RED}Merge conflicts detected! Please resolve them manually.${NC}"
echo "${YELLOW}After resolving:${NC}"
echo " 1. Run: git add <resolved-files>"
echo " 2. Run: git commit"
echo " 3. Run: git push origin $EPIC_BRANCH"
echo " 4. Run this script again to continue with step 2"
exit 1
fi
echo "${YELLOW}Pushing updated $EPIC_BRANCH to remote...${NC}"
if ! git push origin $EPIC_BRANCH; then
echo "${RED}Failed to push epic branch. Try pulling first.${NC}"
echo "${YELLOW}You can run:${NC}"
echo " git pull --rebase origin $EPIC_BRANCH"
echo " git push origin $EPIC_BRANCH"
echo " Then run this script again"
exit 1
fi
# STEP 2: Update feature branch with epic branch
echo ""
echo "${YELLOW}STEP 2: Updating feature branch with epic branch${NC}"
echo "${YELLOW}Switching back to $CURRENT_BRANCH...${NC}"
git checkout $CURRENT_BRANCH || {
echo "${RED}Failed to switch back to your original branch!${NC}"
if [ "$STASHED" = true ]; then
echo "${YELLOW}Your changes are stashed. Restore with: git stash pop${NC}"
fi
exit 1
}
echo "${YELLOW}Merging $EPIC_BRANCH into $CURRENT_BRANCH...${NC}"
if ! git merge $EPIC_BRANCH -m "Merge $EPIC_BRANCH into $CURRENT_BRANCH"; then
echo "${RED}Merge conflicts detected! Please resolve them manually.${NC}"
echo "${YELLOW}After resolving:${NC}"
echo " 1. Run: git add <resolved-files>"
echo " 2. Run: git commit"
# Restore stashed changes if we have them
if [ "$STASHED" = true ]; then
echo "${YELLOW}Your original changes are still stashed. After committing the merge, restore them with: git stash pop${NC}"
fi
exit 1
fi
# Push the updated feature branch
echo "${YELLOW}Pushing updated $CURRENT_BRANCH to remote...${NC}"
if ! git push origin $CURRENT_BRANCH; then
echo "${RED}Failed to push feature branch. You may need to pull first.${NC}"
# Even if push fails, continue to restore stashed changes
echo "${YELLOW}Continuing to restore stashed changes...${NC}"
fi
# Restore stashed changes if needed
if [ "$STASHED" = true ]; then
echo "${YELLOW}Restoring your stashed changes...${NC}"
if ! git stash pop; then
echo "${RED}Conflicts detected when applying your stashed changes!${NC}"
echo "${YELLOW}Please resolve these conflicts manually:${NC}"
echo " 1. Resolve all conflicts in your editor"
echo " 2. Run: git add <resolved-files>"
echo " 3. Run: git commit"
exit 1
fi
fi
echo "${GREEN}Branch sync complete!${NC}"
echo "${GREEN}✓ Updated $EPIC_BRANCH with $MAIN_BRANCH${NC}"
echo "${GREEN}✓ Updated $CURRENT_BRANCH with $EPIC_BRANCH${NC}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment