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