1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano. 4# 5 6USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] (<upstream>|--root) [<branch>] [--quiet | -q]' 7LONG_USAGE='git-rebase replaces <branch> with a new branch of the 8same name. When the --onto option is provided the new branch starts 9out with a HEAD equal to <newbase>, otherwise it is equal to <upstream> 10It then attempts to create a new commit for each commit from the original 11<branch> that does not exist in the <upstream> branch. 12 13It is possible that a merge failure will prevent this process from being 14completely automatic. You will have to resolve any such merge failure 15and run git rebase --continue. Another option is to bypass the commit 16that caused the merge failure with git rebase --skip. To restore the 17original <branch> and remove the .git/rebase-apply working files, use the 18command git rebase --abort instead. 19 20Note that if <branch> is not specified on the command line, the 21currently checked out branch is used. 22 23Example: git-rebase master~1 topic 24 25 A---B---C topic A'\''--B'\''--C'\'' topic 26 / --> / 27 D---E---F---G master D---E---F---G master 28' 29 30SUBDIRECTORY_OK=Yes 31OPTIONS_SPEC= 32. git-sh-setup 33set_reflog_action rebase 34require_work_tree 35cd_to_toplevel 36 37LF=' 38' 39ok_to_skip_pre_rebase= 40resolvemsg=" 41When you have resolved this problem run\"git rebase --continue\". 42If you would prefer to skip this patch, instead run\"git rebase --skip\". 43To restore the original branch and stop rebasing run\"git rebase --abort\". 44" 45unset onto 46strategy= 47strategy_opts= 48do_merge= 49merge_dir="$GIT_DIR"/rebase-merge 50apply_dir="$GIT_DIR"/rebase-apply 51verbose= 52diffstat= 53test"$(git config --bool rebase.stat)"= true && diffstat=t 54git_am_opt= 55rebase_root= 56force_rebase= 57allow_rerere_autoupdate= 58# Non-empty if a rebase was in progress when 'git rebase' was invoked 59in_progress= 60# One of {am, merge, interactive} 61type= 62# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge} 63state_dir= 64# One of {'', continue, skip, abort}, as parsed from command line 65action= 66preserve_merges= 67autosquash= 68test"$(git config --bool rebase.autosquash)"="true"&& autosquash=t 69 70read_basic_state () { 71 head_name=$(cat "$state_dir"/head-name)&& 72 onto=$(cat "$state_dir"/onto)&& 73# We always write to orig-head, but interactive rebase used to write to 74# head. Fall back to reading from head to cover for the case that the 75# user upgraded git with an ongoing interactive rebase. 76iftest -f"$state_dir"/orig-head 77then 78 orig_head=$(cat "$state_dir"/orig-head) 79else 80 orig_head=$(cat "$state_dir"/head) 81fi&& 82 GIT_QUIET=$(cat "$state_dir"/quiet)&& 83test -f"$state_dir"/verbose && verbose=t 84} 85 86write_basic_state () { 87echo"$head_name">"$state_dir"/head-name&& 88echo"$onto">"$state_dir"/onto && 89echo"$orig_head">"$state_dir"/orig-head&& 90echo"$GIT_QUIET">"$state_dir"/quiet && 91test t ="$verbose"&& : >"$state_dir"/verbose 92} 93 94output () { 95case"$verbose"in 96'') 97 output=$("$@" 2>&1 ) 98 status=$? 99test$status!=0&&printf"%s\n""$output" 100return$status 101;; 102*) 103"$@" 104;; 105esac 106} 107 108move_to_original_branch () { 109case"$head_name"in 110 refs/*) 111 message="rebase finished:$head_nameonto$onto" 112 git update-ref -m"$message" \ 113$head_name $(git rev-parse HEAD) $orig_head&& 114 git symbolic-ref HEAD $head_name|| 115 die "Could not move back to$head_name" 116;; 117esac 118} 119 120run_specific_rebase () { 121if["$interactive_rebase"= implied ];then 122 GIT_EDITOR=: 123export GIT_EDITOR 124fi 125 . git-rebase--$type 126} 127 128run_pre_rebase_hook () { 129iftest -z"$ok_to_skip_pre_rebase"&& 130test -x"$GIT_DIR/hooks/pre-rebase" 131then 132"$GIT_DIR/hooks/pre-rebase"${1+"$@"}|| 133 die "The pre-rebase hook refused to rebase." 134fi 135} 136 137test -f"$apply_dir"/applying && 138 die 'It looks like git-am is in progress. Cannot rebase.' 139 140iftest -d"$apply_dir" 141then 142type=am 143 state_dir="$apply_dir" 144eliftest -d"$merge_dir" 145then 146iftest -f"$merge_dir"/interactive 147then 148type=interactive 149 interactive_rebase=explicit 150else 151type=merge 152fi 153 state_dir="$merge_dir" 154fi 155test -n"$type"&& in_progress=t 156 157total_argc=$# 158whiletest$#!=0 159do 160case"$1"in 161--no-verify) 162 ok_to_skip_pre_rebase=yes 163;; 164--verify) 165 ok_to_skip_pre_rebase= 166;; 167--continue|--skip|--abort) 168test$total_argc-eq1|| usage 169 action=${1##--} 170;; 171--onto) 172test2-le"$#"|| usage 173 onto="$2" 174shift 175;; 176-i|--interactive) 177 interactive_rebase=explicit 178;; 179-p|--preserve-merges) 180 preserve_merges=t 181test -z"$interactive_rebase"&& interactive_rebase=implied 182;; 183--autosquash) 184 autosquash=t 185;; 186--no-autosquash) 187 autosquash= 188;; 189-M|-m|--m|--me|--mer|--merg|--merge) 190 do_merge=t 191;; 192-X*|--strategy-option*) 193case"$#,$1"in 1941,-X|1,--strategy-option) 195 usage ;; 196*,-X|*,--strategy-option) 197 newopt="$2" 198shift;; 199*,--strategy-option=*) 200 newopt="$(expr " $1" : ' --strategy-option=\(.*\)')";; 201*,-X*) 202 newopt="$(expr " $1" : ' -X\(.*\)')";; 2031,*) 204 usage ;; 205esac 206 strategy_opts="$strategy_opts$(git rev-parse --sq-quote "--$newopt")" 207 do_merge=t 208test -z"$strategy"&& strategy=recursive 209;; 210-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ 211--strateg=*|--strategy=*|\ 212-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) 213case"$#,$1"in 214*,*=*) 215 strategy=`expr "z$1" : 'z-[^=]*=\(.*\)'`;; 2161,*) 217 usage ;; 218*) 219 strategy="$2" 220shift;; 221esac 222 do_merge=t 223;; 224-n|--no-stat) 225 diffstat= 226;; 227--stat) 228 diffstat=t 229;; 230-v|--verbose) 231 verbose=t 232 diffstat=t 233 GIT_QUIET= 234;; 235-q|--quiet) 236 GIT_QUIET=t 237 git_am_opt="$git_am_opt-q" 238 verbose= 239 diffstat= 240;; 241--whitespace=*) 242 git_am_opt="$git_am_opt$1" 243case"$1"in 244--whitespace=fix|--whitespace=strip) 245 force_rebase=t 246;; 247esac 248;; 249--ignore-whitespace) 250 git_am_opt="$git_am_opt$1" 251;; 252--committer-date-is-author-date|--ignore-date) 253 git_am_opt="$git_am_opt$1" 254 force_rebase=t 255;; 256-C*) 257 git_am_opt="$git_am_opt$1" 258;; 259--root) 260 rebase_root=t 261;; 262-f|--f|--fo|--for|--forc|--force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff) 263 force_rebase=t 264;; 265--rerere-autoupdate|--no-rerere-autoupdate) 266 allow_rerere_autoupdate="$1" 267;; 268-*) 269 usage 270;; 271*) 272break 273;; 274esac 275shift 276done 277test$#-gt2&& usage 278 279iftest -n"$action" 280then 281test -z"$in_progress"&& die "No rebase in progress?" 282# Only interactive rebase uses detailed reflog messages 283iftest"$type"= interactive &&test"$GIT_REFLOG_ACTION"= rebase 284then 285 GIT_REFLOG_ACTION="rebase -i ($action)" 286export GIT_REFLOG_ACTION 287fi 288fi 289 290case"$action"in 291continue) 292# Sanity check 293 git rev-parse --verify HEAD >/dev/null || 294 die "Cannot read HEAD" 295 git update-index --ignore-submodules --refresh&& 296 git diff-files --quiet --ignore-submodules|| { 297echo"You must edit all merge conflicts and then" 298echo"mark them as resolved using git add" 299exit1 300} 301 read_basic_state 302 run_specific_rebase 303;; 304skip) 305 output git reset--hard HEAD ||exit $? 306 read_basic_state 307 run_specific_rebase 308;; 309abort) 310 git rerere clear 311 read_basic_state 312case"$head_name"in 313 refs/*) 314 git symbolic-ref HEAD $head_name|| 315 die "Could not move back to$head_name" 316;; 317esac 318 output git reset--hard$orig_head 319rm-r"$state_dir" 320exit 321;; 322esac 323 324# Make sure no rebase is in progress 325iftest -n"$in_progress" 326then 327 die ' 328It seems that there is already a '"${state_dir##*/}"' directory, and 329I wonder if you are in the middle of another rebase. If that is the 330case, please try 331 git rebase (--continue | --abort | --skip) 332If that is not the case, please 333 rm -fr '"$state_dir"' 334and run me again. I am stopping in case you still have something 335valuable there.' 336fi 337 338test$#-eq0&&test -z"$rebase_root"&& usage 339 340iftest -n"$interactive_rebase" 341then 342type=interactive 343 state_dir="$merge_dir" 344eliftest -n"$do_merge" 345then 346type=merge 347 state_dir="$merge_dir" 348else 349type=am 350 state_dir="$apply_dir" 351fi 352 353iftest -z"$rebase_root" 354then 355# The upstream head must be given. Make sure it is valid. 356 upstream_name="$1" 357shift 358 upstream=`git rev-parse --verify "${upstream_name}^0"`|| 359 die "invalid upstream$upstream_name" 360 upstream_arg="$upstream_name" 361else 362test -z"$onto"&& die "You must specify --onto when using --root" 363unset upstream_name 364unset upstream 365 upstream_arg=--root 366fi 367 368# Make sure the branch to rebase onto is valid. 369onto_name=${onto-"$upstream_name"} 370case"$onto_name"in 371*...*) 372if left=${onto_name%...*} right=${onto_name#*...}&& 373 onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD}) 374then 375case"$onto"in 376 ?*"$LF"?*) 377 die "$onto_name: there are more than one merge bases" 378;; 379'') 380 die "$onto_name: there is no merge base" 381;; 382esac 383else 384 die "$onto_name: there is no merge base" 385fi 386;; 387*) 388 onto=$(git rev-parse --verify "${onto_name}^0")|| 389 die "Does not point to a valid commit:$1" 390;; 391esac 392 393# If the branch to rebase is given, that is the branch we will rebase 394# $branch_name -- branch being rebased, or HEAD (already detached) 395# $orig_head -- commit object name of tip of the branch before rebasing 396# $head_name -- refs/heads/<that-branch> or "detached HEAD" 397switch_to= 398case"$#"in 3991) 400# Is it "rebase other $branchname" or "rebase other $commit"? 401 branch_name="$1" 402 switch_to="$1" 403 404if git show-ref --verify --quiet --"refs/heads/$1"&& 405 orig_head=$(git rev-parse -q --verify "refs/heads/$1") 406then 407 head_name="refs/heads/$1" 408elif orig_head=$(git rev-parse -q --verify "$1") 409then 410 head_name="detached HEAD" 411else 412echo>&2"fatal: no such branch:$1" 413 usage 414fi 415;; 416*) 417# Do not need to switch branches, we are already on it. 418if branch_name=`git symbolic-ref -q HEAD` 419then 420 head_name=$branch_name 421 branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'` 422else 423 head_name="detached HEAD" 424 branch_name=HEAD ;# detached 425fi 426 orig_head=$(git rev-parse --verify "${branch_name}^0")||exit 427;; 428esac 429 430require_clean_work_tree "rebase""Please commit or stash them." 431 432# Now we are rebasing commits $upstream..$orig_head (or with --root, 433# everything leading up to $orig_head) on top of $onto 434 435# Check if we are already based on $onto with linear history, 436# but this should be done only when upstream and onto are the same 437# and if this is not an interactive rebase. 438mb=$(git merge-base "$onto" "$orig_head") 439iftest"$type"!= interactive &&test"$upstream"="$onto"&& 440test"$mb"="$onto"&& 441# linear history? 442! (git rev-list --parents"$onto".."$orig_head"| sane_grep " .* ") > /dev/null 443then 444iftest -z"$force_rebase" 445then 446# Lazily switch to the target branch if needed... 447test -z"$switch_to"|| git checkout "$switch_to"-- 448 say "Current branch$branch_nameis up to date." 449exit0 450else 451 say "Current branch$branch_nameis up to date, rebase forced." 452fi 453fi 454 455# If a hook exists, give it a chance to interrupt 456run_pre_rebase_hook "$upstream_arg""$@" 457 458iftest -n"$diffstat" 459then 460iftest -n"$verbose" 461then 462echo"Changes from$mbto$onto:" 463fi 464# We want color (if set), but no pager 465 GIT_PAGER='' git diff--stat --summary"$mb""$onto" 466fi 467 468test"$type"= interactive && run_specific_rebase 469 470# Detach HEAD and reset the tree 471say "First, rewinding head to replay your work on top of it..." 472git checkout -q"$onto^0"|| die "could not detach HEAD" 473git update-ref ORIG_HEAD $orig_head 474 475# If the $onto is a proper descendant of the tip of the branch, then 476# we just fast-forwarded. 477iftest"$mb"="$orig_head" 478then 479 say "Fast-forwarded$branch_nameto$onto_name." 480 move_to_original_branch 481exit0 482fi 483 484iftest -n"$rebase_root" 485then 486 revisions="$onto..$orig_head" 487else 488 revisions="$upstream..$orig_head" 489fi 490 491run_specific_rebase