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