]>
Commit | Line | Data |
---|---|---|
59e6b23a JH |
1 | #!/bin/sh |
2 | # | |
3 | # Copyright (c) 2005 Junio C Hamano. | |
4 | # | |
5 | ||
e646c9c8 | 6 | USAGE='[--onto <newbase>] <upstream> [<branch>]' |
031321c6 SE |
7 | LONG_USAGE='git-rebase replaces <branch> with a new branch of the |
8 | same name. When the --onto option is provided the new branch starts | |
9 | out with a HEAD equal to <newbase>, otherwise it is equal to <upstream> | |
10 | It then attempts to create a new commit for each commit from the original | |
11 | <branch> that does not exist in the <upstream> branch. | |
69a60af5 | 12 | |
031321c6 SE |
13 | It is possible that a merge failure will prevent this process from being |
14 | completely automatic. You will have to resolve any such merge failure | |
cc120056 SE |
15 | and run git rebase --continue. Another option is to bypass the commit |
16 | that caused the merge failure with git rebase --skip. To restore the | |
17 | original <branch> and remove the .dotest working files, use the command | |
18 | git rebase --abort instead. | |
69a60af5 | 19 | |
031321c6 SE |
20 | Note that if <branch> is not specified on the command line, the |
21 | currently checked out branch is used. You must be in the top | |
22 | directory of your project to start (or continue) a rebase. | |
e646c9c8 | 23 | |
031321c6 | 24 | Example: git-rebase master~1 topic |
e646c9c8 | 25 | |
031321c6 SE |
26 | A---B---C topic A'\''--B'\''--C'\'' topic |
27 | / --> / | |
28 | D---E---F---G master D---E---F---G master | |
e646c9c8 | 29 | ' |
ae2b0f15 | 30 | . git-sh-setup |
4282c4fb | 31 | |
cc120056 SE |
32 | RESOLVEMSG=" |
33 | When you have resolved this problem run \"git rebase --continue\". | |
34 | If you would prefer to skip this patch, instead run \"git rebase --skip\". | |
35 | To restore the original branch and stop rebasing run \"git rebase --abort\". | |
36 | " | |
e646c9c8 JH |
37 | unset newbase |
38 | while case "$#" in 0) break ;; esac | |
39 | do | |
40 | case "$1" in | |
031321c6 SE |
41 | --continue) |
42 | diff=$(git-diff-files) | |
43 | case "$diff" in | |
44 | ?*) echo "You must edit all merge conflicts and then" | |
45 | echo "mark them as resolved using git update-index" | |
46 | exit 1 | |
47 | ;; | |
48 | esac | |
cc120056 SE |
49 | git am --resolved --3way --resolvemsg="$RESOLVEMSG" |
50 | exit | |
51 | ;; | |
52 | --skip) | |
53 | git am -3 --skip --resolvemsg="$RESOLVEMSG" | |
031321c6 SE |
54 | exit |
55 | ;; | |
56 | --abort) | |
57 | [ -d .dotest ] || die "No rebase in progress?" | |
58 | git reset --hard ORIG_HEAD | |
59 | rm -r .dotest | |
60 | exit | |
61 | ;; | |
e646c9c8 JH |
62 | --onto) |
63 | test 2 -le "$#" || usage | |
64 | newbase="$2" | |
65 | shift | |
66 | ;; | |
67 | -*) | |
68 | usage | |
69 | ;; | |
70 | *) | |
71 | break | |
72 | ;; | |
73 | esac | |
74 | shift | |
75 | done | |
2db8aaec | 76 | |
7f4bd5d8 JH |
77 | # Make sure we do not have .dotest |
78 | if mkdir .dotest | |
79 | then | |
80 | rmdir .dotest | |
81 | else | |
82 | echo >&2 ' | |
83 | It seems that I cannot create a .dotest directory, and I wonder if you | |
84 | are in the middle of patch application or another rebase. If that is not | |
85 | the case, please rm -fr .dotest and run me again. I am stopping in case | |
86 | you still have something valuable there.' | |
87 | exit 1 | |
88 | fi | |
89 | ||
7f59dbbb | 90 | # The tree must be really really clean. |
215a7ad1 | 91 | git-update-index --refresh || exit |
7f59dbbb | 92 | diff=$(git-diff-index --cached --name-status -r HEAD) |
32d99544 | 93 | case "$diff" in |
7f59dbbb JH |
94 | ?*) echo "$diff" |
95 | exit 1 | |
96 | ;; | |
97 | esac | |
99a92f92 | 98 | |
e646c9c8 JH |
99 | # The upstream head must be given. Make sure it is valid. |
100 | upstream_name="$1" | |
101 | upstream=`git rev-parse --verify "${upstream_name}^0"` || | |
d0080b3c | 102 | die "invalid upstream $upstream_name" |
32d99544 | 103 | |
9a111c91 JH |
104 | # If a hook exists, give it a chance to interrupt |
105 | if test -x "$GIT_DIR/hooks/pre-rebase" | |
106 | then | |
107 | "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { | |
108 | echo >&2 "The pre-rebase hook refused to rebase." | |
109 | exit 1 | |
110 | } | |
111 | fi | |
112 | ||
7f59dbbb | 113 | # If the branch to rebase is given, first switch to it. |
59e6b23a | 114 | case "$#" in |
7f59dbbb | 115 | 2) |
e646c9c8 | 116 | branch_name="$2" |
3ae39ab2 | 117 | git-checkout "$2" || usage |
e646c9c8 JH |
118 | ;; |
119 | *) | |
120 | branch_name=`git symbolic-ref HEAD` || die "No current branch" | |
f327dbce | 121 | branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` |
e646c9c8 | 122 | ;; |
59e6b23a | 123 | esac |
e646c9c8 | 124 | branch=$(git-rev-parse --verify "${branch_name}^0") || exit |
59e6b23a | 125 | |
e646c9c8 JH |
126 | # Make sure the branch to rebase onto is valid. |
127 | onto_name=${newbase-"$upstream_name"} | |
128 | onto=$(git-rev-parse --verify "${onto_name}^0") || exit | |
32d99544 | 129 | |
e646c9c8 JH |
130 | # Now we are rebasing commits $upstream..$branch on top of $onto |
131 | ||
132 | # Check if we are already based on $onto, but this should be | |
133 | # done only when upstream and onto are the same. | |
b176e6ba | 134 | if test "$upstream" = "$onto" |
7f4bd5d8 | 135 | then |
e646c9c8 JH |
136 | mb=$(git-merge-base "$onto" "$branch") |
137 | if test "$mb" = "$onto" | |
138 | then | |
139 | echo >&2 "Current branch $branch_name is up to date." | |
140 | exit 0 | |
141 | fi | |
7f4bd5d8 JH |
142 | fi |
143 | ||
e646c9c8 JH |
144 | # Rewind the head to "$onto"; this saves our current head in ORIG_HEAD. |
145 | git-reset --hard "$onto" | |
32d99544 | 146 | |
e646c9c8 | 147 | # If the $onto is a proper descendant of the tip of the branch, then |
32d99544 | 148 | # we just fast forwarded. |
e646c9c8 | 149 | if test "$mb" = "$onto" |
32d99544 | 150 | then |
e646c9c8 | 151 | echo >&2 "Fast-forwarded $branch to $newbase." |
32d99544 LS |
152 | exit 0 |
153 | fi | |
154 | ||
e646c9c8 | 155 | git-format-patch -k --stdout --full-index "$upstream" ORIG_HEAD | |
cc120056 SE |
156 | git am --binary -3 -k --resolvemsg="$RESOLVEMSG" |
157 |