diff options
Diffstat (limited to 'git-rebase--interactive.sh')
-rw-r--r-- | git-rebase--interactive.sh | 117 |
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 } |