aboutsummaryrefslogtreecommitdiff
path: root/git-rebase--interactive.sh
diff options
context:
space:
mode:
Diffstat (limited to 'git-rebase--interactive.sh')
-rw-r--r--git-rebase--interactive.sh117
1 files changed, 114 insertions, 3 deletions
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 288227664..c26a200a6 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -156,8 +156,17 @@ Commands:
These lines can be re-ordered; they are executed from top to bottom.
+EOF
+ if test $(get_missing_commit_check_level) = error
+ then
+ git stripspace --comment-lines >>"$todo" <<\EOF
+Do not remove any line. Use 'drop' explicitly to remove a commit.
+EOF
+ else
+ git stripspace --comment-lines >>"$todo" <<\EOF
If you remove a line here THAT COMMIT WILL BE LOST.
EOF
+ fi
}
make_patch () {
@@ -837,6 +846,108 @@ add_exec_commands () {
mv "$1.new" "$1"
}
+# Print the list of the SHA-1 of the commits
+# from stdin to stdout
+todo_list_to_sha_list () {
+ git stripspace --strip-comments |
+ while read -r command sha1 rest
+ do
+ case $command in
+ "$comment_char"*|''|noop|x|"exec")
+ ;;
+ *)
+ long_sha=$(git rev-list --no-walk "$sha1" 2>/dev/null)
+ printf "%s\n" "$long_sha"
+ ;;
+ esac
+ done
+}
+
+# Use warn for each line in stdin
+warn_lines () {
+ while read -r line
+ do
+ warn " - $line"
+ done
+}
+
+# Switch to the branch in $into and notify it in the reflog
+checkout_onto () {
+ GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
+ output git checkout $onto || die_abort "could not detach HEAD"
+ git update-ref ORIG_HEAD $orig_head
+}
+
+get_missing_commit_check_level () {
+ check_level=$(git config --get rebase.missingCommitsCheck)
+ check_level=${check_level:-ignore}
+ # Don't be case sensitive
+ printf '%s' "$check_level" | tr 'A-Z' 'a-z'
+}
+
+# Check if the user dropped some commits by mistake
+# Behaviour determined by rebase.missingCommitsCheck.
+check_todo_list () {
+ raise_error=f
+
+ check_level=$(get_missing_commit_check_level)
+
+ case "$check_level" in
+ warn|error)
+ # Get the SHA-1 of the commits
+ todo_list_to_sha_list <"$todo".backup >"$todo".oldsha1
+ todo_list_to_sha_list <"$todo" >"$todo".newsha1
+
+ # Sort the SHA-1 and compare them
+ sort -u "$todo".oldsha1 >"$todo".oldsha1+
+ mv "$todo".oldsha1+ "$todo".oldsha1
+ sort -u "$todo".newsha1 >"$todo".newsha1+
+ mv "$todo".newsha1+ "$todo".newsha1
+ comm -2 -3 "$todo".oldsha1 "$todo".newsha1 >"$todo".miss
+
+ # Warn about missing commits
+ if test -s "$todo".miss
+ then
+ test "$check_level" = error && raise_error=t
+
+ warn "Warning: some commits may have been dropped" \
+ "accidentally."
+ warn "Dropped commits (newer to older):"
+
+ # Make the list user-friendly and display
+ opt="--no-walk=sorted --format=oneline --abbrev-commit --stdin"
+ git rev-list $opt <"$todo".miss | warn_lines
+
+ warn "To avoid this message, use \"drop\" to" \
+ "explicitly remove a commit."
+ warn
+ warn "Use 'git config rebase.missingCommitsCheck' to change" \
+ "the level of warnings."
+ warn "The possible behaviours are: ignore, warn, error."
+ warn
+ fi
+ ;;
+ ignore)
+ ;;
+ *)
+ warn "Unrecognized setting $check_level for option" \
+ "rebase.missingCommitsCheck. Ignoring."
+ ;;
+ esac
+
+ if test $raise_error = t
+ then
+ # Checkout before the first commit of the
+ # rebase: this way git rebase --continue
+ # will work correctly as it expects HEAD to be
+ # placed before the commit of the next action
+ checkout_onto
+
+ warn "You can fix this with 'git rebase --edit-todo'."
+ die "Or you can abort the rebase with 'git rebase --abort'."
+ fi
+}
+
# The whole contents of this file is run by dot-sourcing it from
# inside a shell function. It used to be that "return"s we see
# below were not inside any function, and expected to return
@@ -1077,13 +1188,13 @@ git_sequence_editor "$todo" ||
has_action "$todo" ||
return 2
+check_todo_list
+
expand_todo_ids
test -d "$rewritten" || test -n "$force_rebase" || skip_unnecessary_picks
-GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
-output git checkout $onto || die_abort "could not detach HEAD"
-git update-ref ORIG_HEAD $orig_head
+checkout_onto
do_rest
}