git-rebase.sh 3.0 KB
Newer Older
1 2 3 4 5
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano.
#

6
USAGE='[--onto <newbase>] <upstream> [<branch>]'
7 8 9 10 11 12 13 14 15
LONG_USAGE='git-rebase applies to <upstream> (or optionally to <newbase>) commits
from <branch> that do not appear in <upstream>. When <branch> is not
specified it defaults to the current branch (HEAD).

When git-rebase is complete, <branch> will be updated to point to the
newly created line of commit objects, so the previous line will not be
accessible unless there are other references to it already.

Assuming the following history:
16 17 18 19 20

          A---B---C topic
         /
    D---E---F---G master

21
The result of the following command:
22

23
    git-rebase --onto master~1 master topic
24

25
  would be:
26

27 28
              A'\''--B'\''--C'\'' topic
             /
29 30 31
    D---E---F---G master
'

32
. git-sh-setup
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
unset newbase
while case "$#" in 0) break ;; esac
do
	case "$1" in
	--onto)
		test 2 -le "$#" || usage
		newbase="$2"
		shift
		;;
	-*)
		usage
		;;
	*)
		break
		;;
	esac
	shift
done
52

53 54 55 56 57 58 59 60 61 62 63 64 65
# Make sure we do not have .dotest
if mkdir .dotest
then
	rmdir .dotest
else
	echo >&2 '
It seems that I cannot create a .dotest directory, and I wonder if you
are in the middle of patch application or another rebase.  If that is not
the case, please rm -fr .dotest and run me again.  I am stopping in case
you still have something valuable there.'
	exit 1
fi

66
# The tree must be really really clean.
J
Junio C Hamano 已提交
67
git-update-index --refresh || exit
68
diff=$(git-diff-index --cached --name-status -r HEAD)
L
Lukas Sandström 已提交
69
case "$diff" in
70 71 72 73
?*)	echo "$diff"
	exit 1
	;;
esac
J
Junio C Hamano 已提交
74

75 76 77
# The upstream head must be given.  Make sure it is valid.
upstream_name="$1"
upstream=`git rev-parse --verify "${upstream_name}^0"` ||
J
Jason Riedy 已提交
78
    die "invalid upstream $upstream_name"
L
Lukas Sandström 已提交
79

80 81 82 83 84 85 86 87 88
# If a hook exists, give it a chance to interrupt
if test -x "$GIT_DIR/hooks/pre-rebase"
then
	"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
		echo >&2 "The pre-rebase hook refused to rebase."
		exit 1
	}
fi

89
# If the branch to rebase is given, first switch to it.
90
case "$#" in
91
2)
92
	branch_name="$2"
93
	git-checkout "$2" || usage
94 95 96 97 98
	;;
*)
	branch_name=`git symbolic-ref HEAD` || die "No current branch"
	branch_name=`expr "$branch_name" : 'refs/heads/\(.*\)'`
	;;
99
esac
100
branch=$(git-rev-parse --verify "${branch_name}^0") || exit
101

102 103 104
# Make sure the branch to rebase onto is valid.
onto_name=${newbase-"$upstream_name"}
onto=$(git-rev-parse --verify "${onto_name}^0") || exit
L
Lukas Sandström 已提交
105

106 107 108 109 110
# Now we are rebasing commits $upstream..$branch on top of $onto

# Check if we are already based on $onto, but this should be
# done only when upstream and onto are the same.
if test "$upstream" = "onto"
111
then
112 113 114 115 116 117
	mb=$(git-merge-base "$onto" "$branch")
	if test "$mb" = "$onto"
	then
		echo >&2 "Current branch $branch_name is up to date."
		exit 0
	fi
118 119
fi

120 121
# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
git-reset --hard "$onto"
L
Lukas Sandström 已提交
122

123
# If the $onto is a proper descendant of the tip of the branch, then
L
Lukas Sandström 已提交
124
# we just fast forwarded.
125
if test "$mb" = "$onto"
L
Lukas Sandström 已提交
126
then
127
	echo >&2 "Fast-forwarded $branch to $newbase."
L
Lukas Sandström 已提交
128 129 130
	exit 0
fi

131
git-format-patch -k --stdout --full-index "$upstream" ORIG_HEAD |
132
git am --binary -3 -k