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