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