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