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