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