@@ -152,11 +152,21 @@ Commands:
152152 s, squash = use commit, but meld into previous commit
153153 f, fixup = like "squash", but discard this commit's log message
154154 x, exec = run command (the rest of the line) using shell
155+ d, drop = remove commit
155156
156157These lines can be re-ordered; they are executed from top to bottom.
157158
159+ EOF
160+ if test $( get_missing_commit_check_level) = error
161+ then
162+ git stripspace --comment-lines >> " $todo " << \EOF
163+ Do not remove any line. Use 'drop' explicitly to remove a commit.
164+ EOF
165+ else
166+ git stripspace --comment-lines >> " $todo " << \EOF
158167If you remove a line here THAT COMMIT WILL BE LOST.
159168EOF
169+ fi
160170}
161171
162172make_patch () {
@@ -505,7 +515,7 @@ do_next () {
505515 rm -f " $msg " " $author_script " " $amend " " $state_dir " /stopped-sha || exit
506516 read -r command sha1 rest < " $todo "
507517 case " $command " in
508- " $comment_char " * |' ' |noop)
518+ " $comment_char " * |' ' |noop|drop|d )
509519 mark_action_done
510520 ;;
511521 pick|p)
@@ -844,6 +854,180 @@ add_exec_commands () {
844854 mv " $1 .new" " $1 "
845855}
846856
857+ # Check if the SHA-1 passed as an argument is a
858+ # correct one, if not then print $2 in "$todo".badsha
859+ # $1: the SHA-1 to test
860+ # $2: the line to display if incorrect SHA-1
861+ check_commit_sha () {
862+ badsha=0
863+ if test -z $1
864+ then
865+ badsha=1
866+ else
867+ sha1_verif=" $( git rev-parse --verify --quiet $1 ^{commit}) "
868+ if test -z $sha1_verif
869+ then
870+ badsha=1
871+ fi
872+ fi
873+
874+ if test $badsha -ne 0
875+ then
876+ warn " Warning: the SHA-1 is missing or isn't" \
877+ " a commit in the following line:"
878+ warn " - $2 "
879+ warn
880+ fi
881+
882+ return $badsha
883+ }
884+
885+ # prints the bad commits and bad commands
886+ # from the todolist in stdin
887+ check_bad_cmd_and_sha () {
888+ retval=0
889+ git stripspace --strip-comments |
890+ (
891+ while read -r line
892+ do
893+ IFS=' '
894+ set -- $line
895+ command=$1
896+ sha1=$2
897+
898+ case $command in
899+ ' ' |noop|x|" exec" )
900+ # Doesn't expect a SHA-1
901+ ;;
902+ pick|p|drop|d|reword|r|edit|e|squash|s|fixup|f)
903+ if ! check_commit_sha $sha1 " $line "
904+ then
905+ retval=1
906+ fi
907+ ;;
908+ * )
909+ warn " Warning: the command isn't recognized" \
910+ " in the following line:"
911+ warn " - $line "
912+ warn
913+ retval=1
914+ ;;
915+ esac
916+ done
917+
918+ return $retval
919+ )
920+ }
921+
922+ # Print the list of the SHA-1 of the commits
923+ # from stdin to stdout
924+ todo_list_to_sha_list () {
925+ git stripspace --strip-comments |
926+ while read -r command sha1 rest
927+ do
928+ case $command in
929+ " $comment_char " * |' ' |noop|x|" exec" )
930+ ;;
931+ * )
932+ long_sha=$( git rev-list --no-walk " $sha1 " 2> /dev/null)
933+ printf " %s\n" " $long_sha "
934+ ;;
935+ esac
936+ done
937+ }
938+
939+ # Use warn for each line in stdin
940+ warn_lines () {
941+ while read -r line
942+ do
943+ warn " - $line "
944+ done
945+ }
946+
947+ # Switch to the branch in $into and notify it in the reflog
948+ checkout_onto () {
949+ GIT_REFLOG_ACTION=" $GIT_REFLOG_ACTION : checkout $onto_name "
950+ output git checkout $onto || die_abort " could not detach HEAD"
951+ git update-ref ORIG_HEAD $orig_head
952+ }
953+
954+ get_missing_commit_check_level () {
955+ check_level=$( git config --get rebase.missingCommitsCheck)
956+ check_level=${check_level:- ignore}
957+ # Don't be case sensitive
958+ printf ' %s' " $check_level " | tr ' A-Z' ' a-z'
959+ }
960+
961+ # Check if the user dropped some commits by mistake
962+ # Behaviour determined by rebase.missingCommitsCheck.
963+ # Check if there is an unrecognized command or a
964+ # bad SHA-1 in a command.
965+ check_todo_list () {
966+ raise_error=f
967+
968+ check_level=$( get_missing_commit_check_level)
969+
970+ case " $check_level " in
971+ warn|error)
972+ # Get the SHA-1 of the commits
973+ todo_list_to_sha_list < " $todo " .backup > " $todo " .oldsha1
974+ todo_list_to_sha_list < " $todo " > " $todo " .newsha1
975+
976+ # Sort the SHA-1 and compare them
977+ sort -u " $todo " .oldsha1 > " $todo " .oldsha1+
978+ mv " $todo " .oldsha1+ " $todo " .oldsha1
979+ sort -u " $todo " .newsha1 > " $todo " .newsha1+
980+ mv " $todo " .newsha1+ " $todo " .newsha1
981+ comm -2 -3 " $todo " .oldsha1 " $todo " .newsha1 > " $todo " .miss
982+
983+ # Warn about missing commits
984+ if test -s " $todo " .miss
985+ then
986+ test " $check_level " = error && raise_error=t
987+
988+ warn " Warning: some commits may have been dropped" \
989+ " accidentally."
990+ warn " Dropped commits (newer to older):"
991+
992+ # Make the list user-friendly and display
993+ opt=" --no-walk=sorted --format=oneline --abbrev-commit --stdin"
994+ git rev-list $opt < " $todo " .miss | warn_lines
995+
996+ warn " To avoid this message, use \" drop\" to" \
997+ " explicitly remove a commit."
998+ warn
999+ warn " Use 'git config rebase.missingCommitsCheck' to change" \
1000+ " the level of warnings."
1001+ warn " The possible behaviours are: ignore, warn, error."
1002+ warn
1003+ fi
1004+ ;;
1005+ ignore)
1006+ ;;
1007+ * )
1008+ warn " Unrecognized setting $check_level for option" \
1009+ " rebase.missingCommitsCheck. Ignoring."
1010+ ;;
1011+ esac
1012+
1013+ if ! check_bad_cmd_and_sha < " $todo "
1014+ then
1015+ raise_error=t
1016+ fi
1017+
1018+ if test $raise_error = t
1019+ then
1020+ # Checkout before the first commit of the
1021+ # rebase: this way git rebase --continue
1022+ # will work correctly as it expects HEAD to be
1023+ # placed before the commit of the next action
1024+ checkout_onto
1025+
1026+ warn " You can fix this with 'git rebase --edit-todo'."
1027+ die " Or you can abort the rebase with 'git rebase --abort'."
1028+ fi
1029+ }
1030+
8471031# The whole contents of this file is run by dot-sourcing it from
8481032# inside a shell function. It used to be that "return"s we see
8491033# below were not inside any function, and expected to return
@@ -1094,13 +1278,13 @@ git_sequence_editor "$todo" ||
10941278has_action " $todo " ||
10951279 return 2
10961280
1281+ check_todo_list
1282+
10971283expand_todo_ids
10981284
10991285test -d " $rewritten " || test -n " $force_rebase " || skip_unnecessary_picks
11001286
1101- GIT_REFLOG_ACTION=" $GIT_REFLOG_ACTION : checkout $onto_name "
1102- output git checkout $onto || die_abort " could not detach HEAD"
1103- git update-ref ORIG_HEAD $orig_head
1287+ checkout_onto
11041288do_rest
11051289
11061290}
0 commit comments