Search code examples
gitdiffgit-rebasegit-diff

diff for git rebase dry-run


I want to see what parts of a topic branch are already included into an upstream branch, and what possible conflicts can arise on rebase.

It should be a kind of dry-run for git-rebase that shows a diff between the topic and the upstream, excluding the changes that don't connect with the topic.


Solution

  • A one solution is to apply diff on the diffs. The idea is:

    1. get diff between forkpoint and topic
    2. get diff between upstream and topic
    3. compare these diffs

    git-diff-rebase script file:

    #!/bin/bash
    
    upstream="$1"
    topic="$2"
    
    root=$( git rev-parse --show-toplevel )
    forkpoint=$( git merge-base $upstream $topic )
    
    if [ -z "$forkpoint" ] ; then
      echo "Merge base is not found" 1>&2
      exit 1
    fi
    
    # list of the changed files (space separated)
    files=$( git -C "$root" diff --name-only $forkpoint $topic | paste -s -d ' ' )
    
    diff -t --tabsize=4 -W $(tput cols) -y --left-column \
      <( git -C "$root" diff $forkpoint $topic ) \
      <( git -C "$root" diff $upstream $topic -- $files ) \
      | grep -vP '(^ *> )' \
      # skip changes that do not interfere with topic (empty left part)
    

    NB: this script should not work for the files with spaces in name.

    Usage: git-diff-rebase master topic | less

    How to interpret the result:

    • * * <     — (empty right part) already included into upstream
    • + * | * — (identic text) already included into upstream
    • - * | + * — conflict
    • + * | - * — possible conflict
    • + * ( — (empty right part) no conflict, absent in the upstream
    • - * ( — (empty right part) no conflict, present in the upstream
    • * ( — (empty right part) present in both topic and upstream

    Where * is placeholder for any text.