contrib/git-svn: add -b/--branch switch for branch detection
[git/repo.git] / git-rebase.sh
blob5956f0654e1b344db7893519e309a45aa22ae16f
1 #!/bin/sh
3 # Copyright (c) 2005 Junio C Hamano.
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).
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.
15 Assuming the following history:
17 A---B---C topic
19 D---E---F---G master
21 The result of the following command:
23 git-rebase --onto master~1 master topic
25 would be:
27 A'\''--B'\''--C'\'' topic
29 D---E---F---G master
32 . git-sh-setup
34 unset newbase
35 while case "$#" in 0) break ;; esac
37 case "$1" in
38 --onto)
39 test 2 -le "$#" || usage
40 newbase="$2"
41 shift
43 -*)
44 usage
47 break
49 esac
50 shift
51 done
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
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
73 esac
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"
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
89 # If the branch to rebase is given, first switch to it.
90 case "$#" in
92 branch_name="$2"
93 git-checkout "$2" || usage
96 branch_name=`git symbolic-ref HEAD` || die "No current branch"
97 branch_name=`expr "$branch_name" : 'refs/heads/\(.*\)'`
99 esac
100 branch=$(git-rev-parse --verify "${branch_name}^0") || exit
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
106 # Now we are rebasing commits $upstream..$branch on top of $onto
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
120 # Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
121 git-reset --hard "$onto"
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
131 git-format-patch -k --stdout --full-index "$upstream" ORIG_HEAD |
132 git am --binary -3 -k