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