Skip to content
Snippets Groups Projects

Script to rebase a MR after reformatting

  • Clone with SSH
  • Clone with HTTPS
  • Embed
  • Share
    The snippet can be accessed without any authentication.
    Authored by Marco Clemencic

    Usage: rebase_and_reformat.sh branch commit_with_reformatting [upstream] where

    • branch: branch you want to rebase
    • commit_with_reformatting: commit where the global reformatting was first introduced (i.e. merge into master)
    • (optional) upstream: target for the final rebase, if different from commit_with_reformatting (useful if you want to rebase to master and the reformatting was applied a few commits ago)
    Edited
    rebase_and_reformat.sh 2.28 KiB
    #!/bin/bash
    
    log() {
      echo -e "\e[0;32m$(date -Is) ===> $@\e[m"
    }
    
    # branch to fix
    branch=${1}
    
    # commit used to merge the initial formatting
    formatting=${2}
    
    # target branch of themerge request
    upstream=${3}
    
    if [ -z "${branch}" -o -z "${formatting}" ] ; then
      echo "usage: ${0} branch commit_with_reformatting [upstream]"
      exit 1
    fi
    
    # no-op (fake) editor
    export GIT_EDITOR=true
    
    # get the branch to fix and make sure there are no spurious conflicts
    log "checking out $branch"
    git checkout $branch
    orig_commit=$(git rev-parse HEAD)
    log "maps to commit $orig_commit"
    
    log "rebase on ${formatting}~"
    if ! git rebase ${formatting}~ ; then
       log "\e[0;31mERROR: rebase failed"
       exit 1
    fi
    
    # start rebasing (reformatting after each commit)
    log "rebase on ${formatting}"
    git rebase --exec 'git diff --diff-filter=MA --no-renames --name-only HEAD~ | xargs -r lb-format && git add -u && git commit --amend --no-edit' ${formatting}
    if [ $? != 0 ] ; then
      log "fixing conflicts"
      # in case of conflict, get our version of the conflicting files...
      git status --porcelain | awk '/^U[UA]/{print $2}' | xargs -r git checkout REBASE_HEAD
      git status --porcelain | awk '/^UD/{print $2}' | xargs -r git rm 
      # ... then continue rebasing ...
      log "continue rebase"
      while ! git rebase --continue ; do
        # ... and repeat
        log "fixing conflicts"
        git status --porcelain | awk '/^U[UA]/{print $2}' | xargs -r git checkout REBASE_HEAD
        git status --porcelain | awk '/^UD/{print $2}' | xargs -r git rm 
        log "continue rebase"
      done
    fi
    log "rebase on ${formatting} completed"
    
    if [ -n "${upstream}" ] ; then
      # after the rebase with only the reformatting, rebase on top of the actual target branch and make sure formatting is consistent
      log "rebase on ${upstream} (with reformatting at each step)"
      if git rebase --exec 'git diff --diff-filter=MA --no-renames --name-only HEAD~ | xargs -r lb-format && git add -u && git commit --amend --no-edit' ${upstream} ; then
        log "rebase on ${upstream} completed"
      else
        log "\e[0;31mERROR: final rebase failed"
        exit 1
      fi
    fi
    
    echo ""
    echo "------------------------------------------------------------"
    echo "Make sure everything is OK before pushing the changes"
    echo "(original version: ${orig_commit})"
    echo "------------------------------------------------------------"
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment