1#!/bin/sh 2# 3# Copyright (c) 2006 Johannes E. Schindelin 4 5# SHORT DESCRIPTION 6# 7# This script makes it easy to fix up commits in the middle of a series, 8# and rearrange commits. 9# 10# The original idea comes from Eric W. Biederman, in 11# http://article.gmane.org/gmane.comp.version-control.git/22407 12 13OPTIONS_KEEPDASHDASH= 14OPTIONS_SPEC="\ 15git-rebase [-i] [options] [--] <upstream> [<branch>] 16git-rebase [-i] (--continue | --abort | --skip) 17-- 18 Available options are 19v,verbose display a diffstat of what changed upstream 20onto= rebase onto given branch instead of upstream 21p,preserve-merges try to recreate merges instead of ignoring them 22s,strategy= use the given merge strategy 23no-ff cherry-pick all commits, even if unchanged 24m,merge always used (no-op) 25i,interactive always used (no-op) 26 Actions: 27continue continue rebasing process 28abort abort rebasing process and restore original branch 29skip skip current patch and continue rebasing process 30no-verify override pre-rebase hook from stopping the operation 31verify allow pre-rebase hook to run 32root rebase all reachable commmits up to the root(s) 33autosquash move commits that begin with squash!/fixup! under -i 34" 35 36. git-sh-setup 37require_work_tree 38 39DOTEST="$GIT_DIR/rebase-merge" 40 41# The file containing rebase commands, comments, and empty lines. 42# This file is created by "git rebase -i" then edited by the user. As 43# the lines are processed, they are removed from the front of this 44# file and written to the tail of $DONE. 45TODO="$DOTEST"/git-rebase-todo 46 47# The rebase command lines that have already been processed. A line 48# is moved here when it is first handled, before any associated user 49# actions. 50DONE="$DOTEST"/done 51 52# The commit message that is planned to be used for any changes that 53# need to be committed following a user interaction. 54MSG="$DOTEST"/message 55 56# The file into which is accumulated the suggested commit message for 57# squash/fixup commands. When the first of a series of squash/fixups 58# is seen, the file is created and the commit message from the 59# previous commit and from the first squash/fixup commit are written 60# to it. The commit message for each subsequent squash/fixup commit 61# is appended to the file as it is processed. 62# 63# The first line of the file is of the form 64# # This is a combination of $COUNT commits. 65# where $COUNT is the number of commits whose messages have been 66# written to the file so far (including the initial "pick" commit). 67# Each time that a commit message is processed, this line is read and 68# updated. It is deleted just before the combined commit is made. 69SQUASH_MSG="$DOTEST"/message-squash 70 71# If the current series of squash/fixups has not yet included a squash 72# command, then this file exists and holds the commit message of the 73# original "pick" commit. (If the series ends without a "squash" 74# command, then this can be used as the commit message of the combined 75# commit without opening the editor.) 76FIXUP_MSG="$DOTEST"/message-fixup 77 78# $REWRITTEN is the name of a directory containing files for each 79# commit that is reachable by at least one merge base of $HEAD and 80# $UPSTREAM. They are not necessarily rewritten, but their children 81# might be. This ensures that commits on merged, but otherwise 82# unrelated side branches are left alone. (Think "X" in the man page's 83# example.) 84REWRITTEN="$DOTEST"/rewritten 85 86DROPPED="$DOTEST"/dropped 87 88# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and 89# GIT_AUTHOR_DATE that will be used for the commit that is currently 90# being rebased. 91AUTHOR_SCRIPT="$DOTEST"/author-script 92 93# When an "edit" rebase command is being processed, the SHA1 of the 94# commit to be edited is recorded in this file. When "git rebase 95# --continue" is executed, if there are any staged changes then they 96# will be amended to the HEAD commit, but only provided the HEAD 97# commit is still the commit to be edited. When any other rebase 98# command is processed, this file is deleted. 99AMEND="$DOTEST"/amend 100 101# For the post-rewrite hook, we make a list of rewritten commits and 102# their new sha1s. The rewritten-pending list keeps the sha1s of 103# commits that have been processed, but not committed yet, 104# e.g. because they are waiting for a 'squash' command. 105REWRITTEN_LIST="$DOTEST"/rewritten-list 106REWRITTEN_PENDING="$DOTEST"/rewritten-pending 107 108PRESERVE_MERGES= 109STRATEGY= 110ONTO= 111VERBOSE= 112OK_TO_SKIP_PRE_REBASE= 113REBASE_ROOT= 114AUTOSQUASH= 115test"$(git config --bool rebase.autosquash)"="true"&& AUTOSQUASH=t 116NEVER_FF= 117 118GIT_CHERRY_PICK_HELP="\ 119hint: after resolving the conflicts, mark the corrected paths 120hint: with 'git add <paths>' and run 'git rebase --continue'" 121export GIT_CHERRY_PICK_HELP 122 123warn () { 124printf'%s\n'"$*">&2 125} 126 127output () { 128case"$VERBOSE"in 129'') 130 output=$("$@" 2>&1 ) 131 status=$? 132test$status!=0&&printf"%s\n""$output" 133return$status 134;; 135*) 136"$@" 137;; 138esac 139} 140 141# Output the commit message for the specified commit. 142commit_message () { 143 git cat-file commit "$1"|sed"1,/^$/d" 144} 145 146run_pre_rebase_hook () { 147iftest -z"$OK_TO_SKIP_PRE_REBASE"&& 148test -x"$GIT_DIR/hooks/pre-rebase" 149then 150"$GIT_DIR/hooks/pre-rebase"${1+"$@"}|| { 151echo>&2"The pre-rebase hook refused to rebase." 152exit1 153} 154fi 155} 156 157 158ORIG_REFLOG_ACTION="$GIT_REFLOG_ACTION" 159 160comment_for_reflog () { 161case"$ORIG_REFLOG_ACTION"in 162''|rebase*) 163 GIT_REFLOG_ACTION="rebase -i ($1)" 164export GIT_REFLOG_ACTION 165;; 166esac 167} 168 169last_count= 170mark_action_done () { 171sed-e1q <"$TODO">>"$DONE" 172sed-e1d <"$TODO">>"$TODO".new 173mv-f"$TODO".new "$TODO" 174 count=$(sane_grep -c '^[^#]' < "$DONE") 175 total=$(($count+$(sane_grep -c '^[^#]' < "$TODO"))) 176iftest"$last_count"!="$count" 177then 178 last_count=$count 179printf"Rebasing (%d/%d)\r"$count $total 180test -z"$VERBOSE"||echo 181fi 182} 183 184make_patch () { 185 sha1_and_parents="$(git rev-list --parents -1 "$1")" 186case"$sha1_and_parents"in 187 ?*' '?*' '?*) 188 git diff--cc$sha1_and_parents 189;; 190 ?*' '?*) 191 git diff-tree -p"$1^!" 192;; 193*) 194echo"Root commit" 195;; 196esac>"$DOTEST"/patch 197test -f"$MSG"|| 198 commit_message "$1">"$MSG" 199test -f"$AUTHOR_SCRIPT"|| 200 get_author_ident_from_commit "$1">"$AUTHOR_SCRIPT" 201} 202 203die_with_patch () { 204echo"$1">"$DOTEST"/stopped-sha 205 make_patch "$1" 206 git rerere 207 die "$2" 208} 209 210die_abort () { 211rm-rf"$DOTEST" 212 die "$1" 213} 214 215has_action () { 216 sane_grep '^[^#]'"$1">/dev/null 217} 218 219# Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and 220# GIT_AUTHOR_DATE exported from the current environment. 221do_with_author () { 222( 223export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE 224"$@" 225) 226} 227 228pick_one () { 229 ff=--ff 230case"$1"in-n) sha1=$2; ff= ;; *) sha1=$1;;esac 231case"$NEVER_FF"in'') ;; ?*) ff= ;;esac 232 output git rev-parse --verify$sha1|| die "Invalid commit name:$sha1" 233test -d"$REWRITTEN"&& 234 pick_one_preserving_merges "$@"&&return 235iftest -n"$REBASE_ROOT" 236then 237 output git cherry-pick"$@" 238return 239fi 240 output git cherry-pick$ff"$@" 241} 242 243pick_one_preserving_merges () { 244 fast_forward=t 245case"$1"in 246-n) 247 fast_forward=f 248 sha1=$2 249;; 250*) 251 sha1=$1 252;; 253esac 254 sha1=$(git rev-parse $sha1) 255 256iftest -f"$DOTEST"/current-commit 257then 258iftest"$fast_forward"= t 259then 260whileread current_commit 261do 262 git rev-parse HEAD >"$REWRITTEN"/$current_commit 263done<"$DOTEST"/current-commit 264rm"$DOTEST"/current-commit|| 265 die "Cannot write current commit's replacement sha1" 266fi 267fi 268 269echo$sha1>>"$DOTEST"/current-commit 270 271# rewrite parents; if none were rewritten, we can fast-forward. 272 new_parents= 273 pend="$(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)" 274iftest"$pend"=" " 275then 276 pend=" root" 277fi 278while["$pend"!=""] 279do 280 p=$(expr "$pend" : ' \([^ ]*\)') 281 pend="${pend# $p}" 282 283 if test -f "$REWRITTEN"/$p 284 then 285 new_p=$(cat "$REWRITTEN"/$p) 286 287 # If the todo reordered commits, and our parent is marked for 288 # rewriting, but hasn't been gotten to yet, assume the user meant to 289# drop it on top of the current HEAD 290iftest -z"$new_p" 291then 292 new_p=$(git rev-parse HEAD) 293fi 294 295test$p!=$new_p&& fast_forward=f 296case"$new_parents"in 297*$new_p*) 298;;# do nothing; that parent is already there 299*) 300 new_parents="$new_parents$new_p" 301;; 302esac 303else 304iftest -f"$DROPPED"/$p 305then 306 fast_forward=f 307 replacement="$(cat "$DROPPED"/$p)" 308test -z"$replacement"&& replacement=root 309 pend="$replacement$pend" 310else 311 new_parents="$new_parents$p" 312fi 313fi 314done 315case$fast_forwardin 316 t) 317 output warn "Fast-forward to$sha1" 318 output git reset--hard$sha1|| 319 die "Cannot fast-forward to$sha1" 320;; 321 f) 322 first_parent=$(expr "$new_parents" : ' \([^ ]*\)') 323 324 if [ "$1" != "-n" ] 325 then 326 # detach HEAD to current parent 327 output git checkout$first_parent2> /dev/null || 328 die "Cannot move HEAD to$first_parent" 329 fi 330 331 case "$new_parents" in 332 ''*''*) 333 test "a$1" = a-n && die "Refusing to squash a merge:$sha1" 334 335 # redo merge 336 author_script=$(get_author_ident_from_commit $sha1) 337 eval "$author_script" 338 msg="$(commit_message $sha1)" 339 # No point in merging the first parent, that's HEAD 340 new_parents=${new_parents# $first_parent} 341if! do_with_author output \ 342 git merge --no-ff$STRATEGY-m"$msg"$new_parents 343then 344printf"%s\n""$msg">"$GIT_DIR"/MERGE_MSG 345 die_with_patch $sha1"Error redoing merge$sha1" 346fi 347echo"$sha1$(git rev-parse HEAD^0)">>"$REWRITTEN_LIST" 348;; 349*) 350 output git cherry-pick"$@"|| 351 die_with_patch $sha1"Could not pick$sha1" 352;; 353esac 354;; 355esac 356} 357 358nth_string () { 359case"$1"in 360*1[0-9]|*[04-9])echo"$1"th;; 361*1)echo"$1"st;; 362*2)echo"$1"nd;; 363*3)echo"$1"rd;; 364esac 365} 366 367update_squash_messages () { 368iftest -f"$SQUASH_MSG";then 369mv"$SQUASH_MSG""$SQUASH_MSG".bak ||exit 370 COUNT=$(($(sed-n \ 371-e"1s/^# This is a combination of \(.*\) commits\./\1/p" \ 372-e"q"<"$SQUASH_MSG".bak)+1)) 373{ 374echo"# This is a combination of$COUNTcommits." 375sed-e1d -e'2,/^./{ 376 /^$/d 377 }'<"$SQUASH_MSG".bak 378} >"$SQUASH_MSG" 379else 380 commit_message HEAD >"$FIXUP_MSG"|| die "Cannot write$FIXUP_MSG" 381 COUNT=2 382{ 383echo"# This is a combination of 2 commits." 384echo"# The first commit's message is:" 385echo 386cat"$FIXUP_MSG" 387} >"$SQUASH_MSG" 388fi 389case$1in 390 squash) 391rm-f"$FIXUP_MSG" 392echo 393echo"# This is the$(nth_string $COUNT)commit message:" 394echo 395 commit_message $2 396;; 397 fixup) 398echo 399echo"# The$(nth_string $COUNT)commit message will be skipped:" 400echo 401 commit_message $2|sed-e's/^/# /' 402;; 403esac>>"$SQUASH_MSG" 404} 405 406peek_next_command () { 407sed-n -e"/^#/d"-e'/^$/d'-e"s/ .*//p"-e"q"<"$TODO" 408} 409 410# A squash/fixup has failed. Prepare the long version of the squash 411# commit message, then die_with_patch. This code path requires the 412# user to edit the combined commit message for all commits that have 413# been squashed/fixedup so far. So also erase the old squash 414# messages, effectively causing the combined commit to be used as the 415# new basis for any further squash/fixups. Args: sha1 rest 416die_failed_squash() { 417mv"$SQUASH_MSG""$MSG"||exit 418rm-f"$FIXUP_MSG" 419cp"$MSG""$GIT_DIR"/MERGE_MSG ||exit 420 warn 421 warn "Could not apply$1...$2" 422 die_with_patch $1"" 423} 424 425flush_rewritten_pending() { 426test -s"$REWRITTEN_PENDING"||return 427 newsha1="$(git rev-parse HEAD^0)" 428sed"s/$/$newsha1/"<"$REWRITTEN_PENDING">>"$REWRITTEN_LIST" 429rm-f"$REWRITTEN_PENDING" 430} 431 432record_in_rewritten() { 433 oldsha1="$(git rev-parse $1)" 434echo"$oldsha1">>"$REWRITTEN_PENDING" 435 436case"$(peek_next_command)"in 437 squash|s|fixup|f) 438;; 439*) 440 flush_rewritten_pending 441;; 442esac 443} 444 445do_next () { 446rm-f"$MSG""$AUTHOR_SCRIPT""$AMEND"||exit 447read -r command sha1 rest <"$TODO" 448case"$command"in 449'#'*|''|noop) 450 mark_action_done 451;; 452 pick|p) 453 comment_for_reflog pick 454 455 mark_action_done 456 pick_one $sha1|| 457 die_with_patch $sha1"Could not apply$sha1...$rest" 458 record_in_rewritten $sha1 459;; 460 reword|r) 461 comment_for_reflog reword 462 463 mark_action_done 464 pick_one $sha1|| 465 die_with_patch $sha1"Could not apply$sha1...$rest" 466 git commit --amend --no-post-rewrite 467 record_in_rewritten $sha1 468;; 469 edit|e) 470 comment_for_reflog edit 471 472 mark_action_done 473 pick_one $sha1|| 474 die_with_patch $sha1"Could not apply$sha1...$rest" 475echo"$sha1">"$DOTEST"/stopped-sha 476 make_patch $sha1 477 git rev-parse --verify HEAD >"$AMEND" 478 warn "Stopped at$sha1...$rest" 479 warn "You can amend the commit now, with" 480 warn 481 warn " git commit --amend" 482 warn 483 warn "Once you are satisfied with your changes, run" 484 warn 485 warn " git rebase --continue" 486 warn 487exit0 488;; 489 squash|s|fixup|f) 490case"$command"in 491 squash|s) 492 squash_style=squash 493;; 494 fixup|f) 495 squash_style=fixup 496;; 497esac 498 comment_for_reflog $squash_style 499 500test -f"$DONE"&& has_action "$DONE"|| 501 die "Cannot '$squash_style' without a previous commit" 502 503 mark_action_done 504 update_squash_messages $squash_style $sha1 505 author_script=$(get_author_ident_from_commit HEAD) 506echo"$author_script">"$AUTHOR_SCRIPT" 507eval"$author_script" 508 output git reset--soft HEAD^ 509 pick_one -n$sha1|| die_failed_squash $sha1"$rest" 510case"$(peek_next_command)"in 511 squash|s|fixup|f) 512# This is an intermediate commit; its message will only be 513# used in case of trouble. So use the long version: 514 do_with_author output git commit --no-verify -F"$SQUASH_MSG"|| 515 die_failed_squash $sha1"$rest" 516;; 517*) 518# This is the final command of this squash/fixup group 519iftest -f"$FIXUP_MSG" 520then 521 do_with_author git commit --no-verify -F"$FIXUP_MSG"|| 522 die_failed_squash $sha1"$rest" 523else 524cp"$SQUASH_MSG""$GIT_DIR"/SQUASH_MSG ||exit 525rm-f"$GIT_DIR"/MERGE_MSG 526 do_with_author git commit --no-verify -e|| 527 die_failed_squash $sha1"$rest" 528fi 529rm-f"$SQUASH_MSG""$FIXUP_MSG" 530;; 531esac 532 record_in_rewritten $sha1 533;; 534 x|"exec") 535read -r command rest <"$TODO" 536 mark_action_done 537printf'Executing: %s\n'"$rest" 538# "exec" command doesn't take a sha1 in the todo-list. 539# => can't just use $sha1 here. 540 git rev-parse --verify HEAD >"$DOTEST"/stopped-sha 541${SHELL:-@SHELL_PATH@}-c"$rest"# Actual execution 542 status=$? 543iftest"$status"-ne0 544then 545 warn "Execution failed:$rest" 546 warn "You can fix the problem, and then run" 547 warn 548 warn " git rebase --continue" 549 warn 550exit"$status" 551fi 552# Run in subshell because require_clean_work_tree can die. 553if! (require_clean_work_tree "rebase") 554then 555 warn "Commit or stash your changes, and then run" 556 warn 557 warn " git rebase --continue" 558 warn 559exit1 560fi 561;; 562*) 563 warn "Unknown command:$command$sha1$rest" 564if git rev-parse --verify -q"$sha1">/dev/null 565then 566 die_with_patch $sha1"Please fix this in the file$TODO." 567else 568 die "Please fix this in the file$TODO." 569fi 570;; 571esac 572test -s"$TODO"&&return 573 574 comment_for_reflog finish && 575 HEADNAME=$(cat "$DOTEST"/head-name)&& 576 OLDHEAD=$(cat "$DOTEST"/head)&& 577 SHORTONTO=$(git rev-parse --short $(cat "$DOTEST"/onto)) && 578 NEWHEAD=$(git rev-parse HEAD)&& 579case$HEADNAMEin 580 refs/*) 581 message="$GIT_REFLOG_ACTION:$HEADNAMEonto$SHORTONTO"&& 582 git update-ref -m"$message"$HEADNAME $NEWHEAD $OLDHEAD&& 583 git symbolic-ref HEAD $HEADNAME 584;; 585esac&& { 586test!-f"$DOTEST"/verbose || 587 git diff-tree --stat$(cat "$DOTEST"/head)..HEAD 588} && 589{ 590test -s"$REWRITTEN_LIST"&& 591 git notes copy --for-rewrite=rebase <"$REWRITTEN_LIST"|| 592 true # we don't care if this copying failed 593} && 594iftest -x"$GIT_DIR"/hooks/post-rewrite&& 595test -s"$REWRITTEN_LIST";then 596"$GIT_DIR"/hooks/post-rewrite rebase <"$REWRITTEN_LIST" 597 true # we don't care if this hook failed 598fi&& 599rm-rf"$DOTEST"&& 600 git gc --auto&& 601 warn "Successfully rebased and updated$HEADNAME." 602 603exit 604} 605 606do_rest () { 607while: 608do 609 do_next 610done 611} 612 613# skip picking commits whose parents are unchanged 614skip_unnecessary_picks () { 615 fd=3 616whileread -r command rest 617do 618# fd=3 means we skip the command 619case"$fd,$command"in 6203,pick|3,p) 621# pick a commit whose parent is current $ONTO -> skip 622 sha1=${rest%% *} 623case"$(git rev-parse --verify --quiet "$sha1"^)"in 624"$ONTO"*) 625 ONTO=$sha1 626;; 627*) 628 fd=1 629;; 630esac 631;; 6323,#*|3,) 633# copy comments 634;; 635*) 636 fd=1 637;; 638esac 639printf'%s\n'"$command${rest:+ }$rest">&$fd 640done<"$TODO">"$TODO.new"3>>"$DONE"&& 641mv-f"$TODO".new "$TODO"&& 642case"$(peek_next_command)"in 643 squash|s|fixup|f) 644 record_in_rewritten "$ONTO" 645;; 646esac|| 647 die "Could not skip unnecessary pick commands" 648} 649 650# check if no other options are set 651is_standalone () { 652test$#-eq2-a"$2"='--'&& 653test -z"$ONTO"&& 654test -z"$PRESERVE_MERGES"&& 655test -z"$STRATEGY"&& 656test -z"$VERBOSE" 657} 658 659get_saved_options () { 660test -d"$REWRITTEN"&& PRESERVE_MERGES=t 661test -f"$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)" 662test -f"$DOTEST"/verbose && VERBOSE=t 663test -f"$DOTEST"/rebase-root&& REBASE_ROOT=t 664} 665 666# Rearrange the todo list that has both "pick sha1 msg" and 667# "pick sha1 fixup!/squash! msg" appears in it so that the latter 668# comes immediately after the former, and change "pick" to 669# "fixup"/"squash". 670rearrange_squash () { 671# extract fixup!/squash! lines and resolve any referenced sha1's 672whileread -r pick sha1 message 673do 674case"$message"in 675"squash! "*|"fixup! "*) 676 action="${message%%!*}" 677 rest="${message#*! }" 678echo"$sha1$action$rest" 679# if it's a single word, try to resolve to a full sha1 and 680# emit a second copy. This allows us to match on both message 681# and on sha1 prefix 682iftest"${rest#* }"="$rest";then 683 fullsha="$(git rev-parse -q --verify "$rest" 2>/dev/null)" 684iftest -n"$fullsha";then 685# prefix the action to uniquely identify this line as 686# intended for full sha1 match 687echo"$sha1+$action$fullsha" 688fi 689fi 690esac 691done>"$1.sq"<"$1" 692test -s"$1.sq"||return 693 694 used= 695whileread -r pick sha1 message 696do 697case"$used"in 698*"$sha1"*)continue;; 699esac 700printf'%s\n'"$pick$sha1$message" 701 used="$used$sha1" 702whileread -r squash action msg 703do 704case"$used"in 705*"$squash"*)continue;; 706esac 707 emit=0 708case"$action"in 709+*) 710 action="${action#+}" 711# full sha1 prefix test 712case"$msg"in"$sha1"*) emit=1;;esac;; 713*) 714# message prefix test 715case"$message"in"$msg"*) emit=1;;esac;; 716esac 717iftest$emit=1;then 718printf'%s\n'"$action$squash$action!$msg" 719 used="$used$squash" 720fi 721done<"$1.sq" 722done>"$1.rearranged"<"$1" 723cat"$1.rearranged">"$1" 724rm-f"$1.sq""$1.rearranged" 725} 726 727LF=' 728' 729parse_onto () { 730case"$1"in 731*...*) 732if left=${1%...*} right=${1#*...}&& 733 onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD}) 734then 735case"$onto"in 736 ?*"$LF"?* |'') 737exit1;; 738esac 739echo"$onto" 740exit0 741fi 742esac 743 git rev-parse --verify"$1^0" 744} 745 746whiletest$#!=0 747do 748case"$1"in 749--no-verify) 750 OK_TO_SKIP_PRE_REBASE=yes 751;; 752--verify) 753 OK_TO_SKIP_PRE_REBASE= 754;; 755--continue) 756 is_standalone "$@"|| usage 757 get_saved_options 758 comment_for_reflog continue 759 760test -d"$DOTEST"|| die "No interactive rebase running" 761 762# Sanity check 763 git rev-parse --verify HEAD >/dev/null || 764 die "Cannot read HEAD" 765 git update-index --ignore-submodules --refresh&& 766 git diff-files --quiet --ignore-submodules|| 767 die "Working tree is dirty" 768 769# do we have anything to commit? 770if git diff-index --cached --quiet --ignore-submodules HEAD -- 771then 772: Nothing to commit -- skip this 773else 774 . "$AUTHOR_SCRIPT"|| 775 die "Cannot find the author identity" 776 amend= 777iftest -f"$AMEND" 778then 779 amend=$(git rev-parse --verify HEAD) 780test"$amend"=$(cat "$AMEND")|| 781 die "\ 782You have uncommitted changes in your working tree. Please, commit them 783first and then run 'git rebase --continue' again." 784 git reset--soft HEAD^ || 785 die "Cannot rewind the HEAD" 786fi 787 do_with_author git commit --no-verify -F"$MSG"-e|| { 788test -n"$amend"&& git reset--soft$amend 789 die "Could not commit staged changes." 790} 791fi 792 793 record_in_rewritten "$(cat "$DOTEST"/stopped-sha)" 794 795 require_clean_work_tree "rebase" 796 do_rest 797;; 798--abort) 799 is_standalone "$@"|| usage 800 get_saved_options 801 comment_for_reflog abort 802 803 git rerere clear 804test -d"$DOTEST"|| die "No interactive rebase running" 805 806 HEADNAME=$(cat "$DOTEST"/head-name) 807 HEAD=$(cat "$DOTEST"/head) 808case$HEADNAMEin 809 refs/*) 810 git symbolic-ref HEAD $HEADNAME 811;; 812esac&& 813 output git reset--hard$HEAD&& 814rm-rf"$DOTEST" 815exit 816;; 817--skip) 818 is_standalone "$@"|| usage 819 get_saved_options 820 comment_for_reflog skip 821 822 git rerere clear 823test -d"$DOTEST"|| die "No interactive rebase running" 824 825 output git reset--hard&& do_rest 826;; 827-s) 828case"$#,$1"in 829*,*=*) 830 STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; 831 1,*) 832 usage ;; 833 *) 834 STRATEGY="-s$2" 835 shift ;; 836 esac 837 ;; 838 -m) 839 # we use merge anyway 840 ;; 841 -v) 842 VERBOSE=t 843 ;; 844 -p) 845 PRESERVE_MERGES=t 846 ;; 847 -i) 848 # yeah, we know 849 ;; 850 --no-ff) 851 NEVER_FF=t 852 ;; 853 --root) 854 REBASE_ROOT=t 855 ;; 856 --autosquash) 857 AUTOSQUASH=t 858 ;; 859 --no-autosquash) 860 AUTOSQUASH= 861 ;; 862 --onto) 863 shift 864 ONTO=$(parse_onto "$1")|| 865 die "Does not point to a valid commit:$1" 866 ;; 867 --) 868 shift 869 test -z "$REBASE_ROOT" -a$#-ge 1 -a$#-le 2 || 870 test ! -z "$REBASE_ROOT" -a$#-le 1 || usage 871 test -d "$DOTEST" && 872 die "Interactive rebase already started" 873 874 git var GIT_COMMITTER_IDENT >/dev/null || 875 die "You need to set your committer info first" 876 877 if test -z "$REBASE_ROOT" 878 then 879 UPSTREAM_ARG="$1" 880 UPSTREAM=$(git rev-parse --verify "$1")|| die "Invalid base" 881 test -z "$ONTO" && ONTO=$UPSTREAM 882 shift 883 else 884 UPSTREAM= 885 UPSTREAM_ARG=--root 886 test -z "$ONTO" && 887 die "You must specify --onto when using --root" 888 fi 889 run_pre_rebase_hook "$UPSTREAM_ARG" "$@" 890 891 comment_for_reflog start 892 893 require_clean_work_tree "rebase" "Please commit or stash them." 894 895 if test ! -z "$1" 896 then 897 output git checkout "$1" -- || 898 die "Could not checkout$1" 899 fi 900 901 HEAD=$(git rev-parse --verify HEAD)|| die "No HEAD?" 902 mkdir "$DOTEST" || die "Could not create temporary$DOTEST" 903 904 : > "$DOTEST"/interactive || die "Could not mark as interactive" 905 git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null || 906 echo "detached HEAD" > "$DOTEST"/head-name 907 908 echo$HEAD> "$DOTEST"/head 909 case "$REBASE_ROOT" in 910 '') 911 rm -f "$DOTEST"/rebase-root ;; 912 *) 913 : >"$DOTEST"/rebase-root ;; 914 esac 915 echo$ONTO> "$DOTEST"/onto 916 test -z "$STRATEGY" || echo "$STRATEGY" > "$DOTEST"/strategy 917 test t = "$VERBOSE" && : > "$DOTEST"/verbose 918 if test t = "$PRESERVE_MERGES" 919 then 920 if test -z "$REBASE_ROOT" 921 then 922 mkdir "$REWRITTEN" && 923 for c in$(git merge-base --all $HEAD $UPSTREAM) 924 do 925 echo$ONTO> "$REWRITTEN"/$c|| 926 die "Could not init rewritten commits" 927 done 928 else 929 mkdir "$REWRITTEN" && 930 echo$ONTO> "$REWRITTEN"/root || 931 die "Could not init rewritten commits" 932 fi 933 # No cherry-pick because our first pass is to determine 934 # parents to rewrite and skipping dropped commits would 935 # prematurely end our probe 936 MERGES_OPTION= 937 first_after_upstream="$(git rev-list --reverse --first-parent $UPSTREAM..$HEAD | head -n 1)" 938 else 939 MERGES_OPTION="--no-merges --cherry-pick" 940 fi 941 942 SHORTHEAD=$(git rev-parse --short $HEAD) 943 SHORTONTO=$(git rev-parse --short $ONTO) 944 if test -z "$REBASE_ROOT" 945 # this is now equivalent to ! -z "$UPSTREAM" 946 then 947 SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM) 948 REVISIONS=$UPSTREAM...$HEAD 949 SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD 950 else 951 REVISIONS=$ONTO...$HEAD 952 SHORTREVISIONS=$SHORTHEAD 953 fi 954 git rev-list$MERGES_OPTION--pretty=oneline --abbrev-commit \ 955 --abbrev=7 --reverse --left-right --topo-order \ 956$REVISIONS| \ 957 sed -n "s/^>//p" | 958 while read -r shortsha1 rest 959 do 960 if test t != "$PRESERVE_MERGES" 961 then 962 printf '%s\n' "pick$shortsha1$rest" >> "$TODO" 963 else 964 sha1=$(git rev-parse $shortsha1) 965 if test -z "$REBASE_ROOT" 966 then 967 preserve=t 968 for p in$(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-) 969 do 970 if test -f "$REWRITTEN"/$p-a \($p!=$ONTO-o$sha1=$first_after_upstream\) 971 then 972 preserve=f 973 fi 974 done 975 else 976 preserve=f 977 fi 978 if test f = "$preserve" 979 then 980 touch "$REWRITTEN"/$sha1 981 printf '%s\n' "pick$shortsha1$rest" >> "$TODO" 982 fi 983 fi 984 done 985 986 # Watch for commits that been dropped by --cherry-pick 987 if test t = "$PRESERVE_MERGES" 988 then 989 mkdir "$DROPPED" 990 # Save all non-cherry-picked changes 991 git rev-list$REVISIONS--left-right --cherry-pick | \ 992 sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks 993 # Now all commits and note which ones are missing in 994 # not-cherry-picks and hence being dropped 995 git rev-list$REVISIONS| 996 while read rev 997 do 998 if test -f "$REWRITTEN"/$rev-a "$(sane_grep "$rev" "$DOTEST"/not-cherry-picks)" = "" 999 then1000 # Use -f2 because if rev-list is telling us this commit is1001 # not worthwhile, we don't want to track its multiple heads,1002# just the history of its first-parent for others that will1003# be rebasing on top of it1004 git rev-list --parents -1$rev| cut -d' '-s -f2>"$DROPPED"/$rev1005 short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)1006 sane_grep -v"^[a-z][a-z]*$short"<"$TODO">"${TODO}2";mv"${TODO}2""$TODO"1007rm"$REWRITTEN"/$rev1008fi1009done1010fi10111012test -s"$TODO"||echo noop >>"$TODO"1013test -n"$AUTOSQUASH"&& rearrange_squash "$TODO"1014cat>>"$TODO"<< EOF10151016# Rebase$SHORTREVISIONSonto$SHORTONTO1017#1018# Commands:1019# p, pick = use commit1020# r, reword = use commit, but edit the commit message1021# e, edit = use commit, but stop for amending1022# s, squash = use commit, but meld into previous commit1023# f, fixup = like "squash", but discard this commit's log message1024# x, exec = run command (the rest of the line) using shell1025#1026# If you remove a line here THAT COMMIT WILL BE LOST.1027# However, if you remove everything, the rebase will be aborted.1028#1029EOF10301031 has_action "$TODO"||1032 die_abort "Nothing to do"10331034cp"$TODO""$TODO".backup1035 git_editor "$TODO"||1036 die_abort "Could not execute editor"10371038 has_action "$TODO"||1039 die_abort "Nothing to do"10401041test -d"$REWRITTEN"||test -n"$NEVER_FF"|| skip_unnecessary_picks10421043 output git checkout $ONTO|| die_abort "could not detach HEAD"1044 git update-ref ORIG_HEAD $HEAD1045 do_rest1046;;1047esac1048shift1049done