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