@@ -152,11 +152,21 @@ Commands:
152
152
s, squash = use commit, but meld into previous commit
153
153
f, fixup = like "squash", but discard this commit's log message
154
154
x, exec = run command (the rest of the line) using shell
155
+ d, drop = remove commit
155
156
156
157
These lines can be re-ordered; they are executed from top to bottom.
157
158
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
158
167
If you remove a line here THAT COMMIT WILL BE LOST.
159
168
EOF
169
+ fi
160
170
}
161
171
162
172
make_patch () {
@@ -505,7 +515,7 @@ do_next () {
505
515
rm -f " $msg " " $author_script " " $amend " " $state_dir " /stopped-sha || exit
506
516
read -r command sha1 rest < " $todo "
507
517
case " $command " in
508
- " $comment_char " * |' ' |noop)
518
+ " $comment_char " * |' ' |noop|drop|d )
509
519
mark_action_done
510
520
;;
511
521
pick|p)
@@ -844,6 +854,180 @@ add_exec_commands () {
844
854
mv " $1 .new" " $1 "
845
855
}
846
856
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
+
847
1031
# The whole contents of this file is run by dot-sourcing it from
848
1032
# inside a shell function. It used to be that "return"s we see
849
1033
# below were not inside any function, and expected to return
@@ -1094,13 +1278,13 @@ git_sequence_editor "$todo" ||
1094
1278
has_action " $todo " ||
1095
1279
return 2
1096
1280
1281
+ check_todo_list
1282
+
1097
1283
expand_todo_ids
1098
1284
1099
1285
test -d " $rewritten " || test -n " $force_rebase " || skip_unnecessary_picks
1100
1286
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
1104
1288
do_rest
1105
1289
1106
1290
}
0 commit comments