git-rebase.shon commit fsck-objects: mark objects reachable from cache-tree (cdc08b3)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano.
   4#
   5
   6USAGE='[--onto <newbase>] <upstream> [<branch>]'
   7LONG_USAGE='git-rebase applies to <upstream> (or optionally to <newbase>) commits
   8from <branch> that do not appear in <upstream>. When <branch> is not
   9specified it defaults to the current branch (HEAD).
  10
  11When git-rebase is complete, <branch> will be updated to point to the
  12newly created line of commit objects, so the previous line will not be
  13accessible unless there are other references to it already.
  14
  15Assuming the following history:
  16
  17          A---B---C topic
  18         /
  19    D---E---F---G master
  20
  21The result of the following command:
  22
  23    git-rebase --onto master~1 master topic
  24
  25  would be:
  26
  27              A'\''--B'\''--C'\'' topic
  28             /
  29    D---E---F---G master
  30'
  31
  32. git-sh-setup
  33
  34unset newbase
  35while case "$#" in 0) break ;; esac
  36do
  37        case "$1" in
  38        --onto)
  39                test 2 -le "$#" || usage
  40                newbase="$2"
  41                shift
  42                ;;
  43        -*)
  44                usage
  45                ;;
  46        *)
  47                break
  48                ;;
  49        esac
  50        shift
  51done
  52
  53# Make sure we do not have .dotest
  54if mkdir .dotest
  55then
  56        rmdir .dotest
  57else
  58        echo >&2 '
  59It seems that I cannot create a .dotest directory, and I wonder if you
  60are in the middle of patch application or another rebase.  If that is not
  61the case, please rm -fr .dotest and run me again.  I am stopping in case
  62you still have something valuable there.'
  63        exit 1
  64fi
  65
  66# The tree must be really really clean.
  67git-update-index --refresh || exit
  68diff=$(git-diff-index --cached --name-status -r HEAD)
  69case "$diff" in
  70?*)     echo "$diff"
  71        exit 1
  72        ;;
  73esac
  74
  75# The upstream head must be given.  Make sure it is valid.
  76upstream_name="$1"
  77upstream=`git rev-parse --verify "${upstream_name}^0"` ||
  78    die "invalid upstream $upstream_name"
  79
  80# If a hook exists, give it a chance to interrupt
  81if test -x "$GIT_DIR/hooks/pre-rebase"
  82then
  83        "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
  84                echo >&2 "The pre-rebase hook refused to rebase."
  85                exit 1
  86        }
  87fi
  88
  89# If the branch to rebase is given, first switch to it.
  90case "$#" in
  912)
  92        branch_name="$2"
  93        git-checkout "$2" || usage
  94        ;;
  95*)
  96        branch_name=`git symbolic-ref HEAD` || die "No current branch"
  97        branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
  98        ;;
  99esac
 100branch=$(git-rev-parse --verify "${branch_name}^0") || exit
 101
 102# Make sure the branch to rebase onto is valid.
 103onto_name=${newbase-"$upstream_name"}
 104onto=$(git-rev-parse --verify "${onto_name}^0") || exit
 105
 106# Now we are rebasing commits $upstream..$branch on top of $onto
 107
 108# Check if we are already based on $onto, but this should be
 109# done only when upstream and onto are the same.
 110if test "$upstream" = "$onto"
 111then
 112        mb=$(git-merge-base "$onto" "$branch")
 113        if test "$mb" = "$onto"
 114        then
 115                echo >&2 "Current branch $branch_name is up to date."
 116                exit 0
 117        fi
 118fi
 119
 120# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
 121git-reset --hard "$onto"
 122
 123# If the $onto is a proper descendant of the tip of the branch, then
 124# we just fast forwarded.
 125if test "$mb" = "$onto"
 126then
 127        echo >&2 "Fast-forwarded $branch to $newbase."
 128        exit 0
 129fi
 130
 131git-format-patch -k --stdout --full-index "$upstream" ORIG_HEAD |
 132git am --binary -3 -k