Merge branch 'sp/checkout'
[git] / git-rebase.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano.
4 #
5
6 USAGE='[--onto <newbase>] <upstream> [<branch>]'
7 LONG_USAGE='git-rebase applies to <upstream> (or optionally to <newbase>) commits
8 from <branch> that do not appear in <upstream>. When <branch> is not
9 specified it defaults to the current branch (HEAD).
10
11 When git-rebase is complete, <branch> will be updated to point to the
12 newly created line of commit objects, so the previous line will not be
13 accessible unless there are other references to it already.
14
15 Assuming the following history:
16
17           A---B---C topic
18          /
19     D---E---F---G master
20
21 The 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
34 unset newbase
35 while case "$#" in 0) break ;; esac
36 do
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
51 done
52
53 # Make sure we do not have .dotest
54 if mkdir .dotest
55 then
56         rmdir .dotest
57 else
58         echo >&2 '
59 It seems that I cannot create a .dotest directory, and I wonder if you
60 are in the middle of patch application or another rebase.  If that is not
61 the case, please rm -fr .dotest and run me again.  I am stopping in case
62 you still have something valuable there.'
63         exit 1
64 fi
65
66 # The tree must be really really clean.
67 git-update-index --refresh || exit
68 diff=$(git-diff-index --cached --name-status -r HEAD)
69 case "$diff" in
70 ?*)     echo "$diff"
71         exit 1
72         ;;
73 esac
74
75 # The upstream head must be given.  Make sure it is valid.
76 upstream_name="$1"
77 upstream=`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
81 if test -x "$GIT_DIR/hooks/pre-rebase"
82 then
83         "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
84                 echo >&2 "The pre-rebase hook refused to rebase."
85                 exit 1
86         }
87 fi
88
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         branch_name=`git symbolic-ref HEAD` || die "No current branch"
97         branch_name=`expr "$branch_name" : 'refs/heads/\(.*\)'`
98         ;;
99 esac
100 branch=$(git-rev-parse --verify "${branch_name}^0") || exit
101
102 # Make sure the branch to rebase onto is valid.
103 onto_name=${newbase-"$upstream_name"}
104 onto=$(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.
110 if test "$upstream" = "onto"
111 then
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
118 fi
119
120 # Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
121 git-reset --hard "$onto"
122
123 # If the $onto is a proper descendant of the tip of the branch, then
124 # we just fast forwarded.
125 if test "$mb" = "$onto"
126 then
127         echo >&2 "Fast-forwarded $branch to $newbase."
128         exit 0
129 fi
130
131 git-format-patch -k --stdout --full-index "$upstream" ORIG_HEAD |
132 git am --binary -3 -k