Check if commits were removed (i.e. a line was deleted) and print
warnings or abort git rebase according to the value of the
configuration variable rebase.missingCommitsCheckLevel.
Add the configuration variable rebase.missingCommitsCheckLevel.
- When unset or set to "ignore", no checking is done.
- When set to "warn", the commits are checked, warnings are
displayed but git rebase still proceeds.
- When set to "error", the commits are checked, warnings are
displayed and the rebase is aborted.
rebase.missingCommitsCheckLevel defaults to "ignore".
Signed-off-by: Galan Rémi <[email protected]>
---
Documentation/config.txt | 7 +++
Documentation/git-rebase.txt | 6 +++
git-rebase--interactive.sh | 105 ++++++++++++++++++++++++++++++++++++++++++
t/t3404-rebase-interactive.sh | 25 ++++++++++
4 files changed, 143 insertions(+)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 4d21ce1..ec9011d 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2160,6 +2160,13 @@ rebase.autoStash::
successful rebase might result in non-trivial conflicts.
Defaults to false.
+rebase.missingCommitsCheckLevel::
+ If set to "warn", git rebase -i will print a warning if some
+ commits are removed (i.e. a line was deleted), however the
+ rebase will still proceed. If set to "error", it will print
+ the previous warning and abort the rebase. If set to
+ "ignore", no checking is done. Defaults to "ignore".
+
receive.advertiseAtomic::
By default, git-receive-pack will advertise the atomic push
capability to its clients. If you don't want to this capability
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 9cf3760..71029f8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -213,6 +213,12 @@ rebase.autoSquash::
rebase.autoStash::
If set to true enable '--autostash' option by default.
+rebase.missingCommitsCheckLevel::
+ If set to "warn" print warnings about removed commits in
+ interactive mode. If set to "error" print the warnings and
+ abort the rebase. If set to "ignore" no checking is
+ done. "ignore" by default.
+
OPTIONS
-------
--onto <newbase>::
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 869cc60..6391423 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -851,6 +851,109 @@ add_exec_commands () {
mv "$1.new" "$1"
}
+# Print the list of the SHA-1 of the commits
+# from a todo list in a file.
+# $1: todo-file, $2: outfile
+todo_list_to_sha_list () {
+ todo_list=$(git stripspace --strip-comments <"$1")
+ temp_file=$(mktemp)
+ echo "$todo_list" >$temp_file
+ while read -r command sha1 rest
+ do
+ case $command in
+ x|"exec")
+ ;;
+ *)
+ printf "%s\n" "$sha1"
+ ;;
+ esac
+ done <$temp_file >"$2"
+ rm $temp_file
+}
+
+# Transforms SHA-1 list in argument
+# to a list of commits (in place)
+# Doesn't check if the SHA-1 are commits.
+# $1: file with long SHA-1 list
+long_sha_to_commit_list () {
+ short_missing=""
+ git_command="git show --oneline"
+ get_line_command="head -n 1"
+ temp_file=$(mktemp)
+ while read -r sha
+ do
+ if test -n "$sha"
+ then
+ commit=$($git_command $sha | $get_line_command)
+ if test -n "$commit"
+ then
+ printf "%s\n" "$commit"
+ fi
+ fi
+ done <"$1" >$temp_file
+ mv $temp_file "$1"
+}
+
+# Use warn for each line of a file
+# $1: file to warn
+warn_file () {
+ while read -r line
+ do
+ warn " - $line"
+ done <"$1"
+}
+
+# Check if the user dropped some commits by mistake
+# Behaviour determined by .gitconfig.
+check_commits () {
+ checkLevel=$(git config --get rebase.missingCommitsCheckLevel)
+ checkLevel=${checkLevel:-ignore}
+ # To lowercase
+ checkLevel=$(echo "$checkLevel" | tr 'A-Z' 'a-z')
+
+ case "$checkLevel" 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
+ echo "$(sort -u "$todo".oldsha1)" >"$todo".oldsha1
+ echo "$(sort -u "$todo".newsha1)" >"$todo".newsha1
+ echo "$(comm -2 -3 "$todo".oldsha1 "$todo".newsha1)"
>"$todo".miss
+
+ # Make the list user-friendly
+ long_sha_to_commit_list "$todo".miss
+
+ # Check missing commits
+ if test -s "$todo".miss
+ then
+ warn "Warning : some commits may have been dropped" \
+ "accidentally."
+ warn "Dropped commits (in no relevent order):"
+ warn_file "$todo".miss
+ warn ""
+ warn "To avoid this message, use \"drop\" to" \
+ "explicitly remove a commit."
+ warn "Use git --config rebase.missingCommitsCheckLevel
to change" \
+ "the level of warnings (ignore,warn,error)."
+ warn ""
+
+ if test "$checkLevel" = error
+ then
+ die_abort "Rebase aborted due to dropped
commits."
+ fi
+ fi
+ ;;
+ ignore)
+ ;;
+ *)
+ warn "Unrecognized setting $checkLevel for option" \
+ "rebase.missingCommitsCheckLevel in git rebase -i."
+ ;;
+ esac
+}
+
# 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
@@ -1096,6 +1199,8 @@ has_action "$todo" ||
expand_todo_ids
+check_commits
+
test -d "$rewritten" || test -n "$force_rebase" || skip_unnecessary_picks
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 8960083..07a7158 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1112,4 +1112,29 @@ test_expect_success 'drop' '
test A = $(git cat-file commit HEAD^^ | sed -ne \$p)
'
+test_expect_success 'rebase -i respects rebase.missingCommitsCheckLevel=error'
'
+ test_config rebase.missingCommitsCheckLevel error &&
+ test_when_finished "git checkout master &&
+ git branch -D tmp2" &&
+ git checkout -b tmp2 master &&
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="1 2 3 4" \
+ git rebase -i --root &&
+ test E = $(git cat-file commit HEAD | sed -ne \$p)
+'
+
+test_expect_success 'rebase -i respects rebase.missingCommitsCheckLevel=warn' '
+ test_config rebase.missingCommitsCheckLevel warn &&
+ test_when_finished "git checkout master &&
+ git branch -D tmp2" &&
+ git checkout -b tmp2 master &&
+ set_fake_editor &&
+ FAKE_LINES="1 2 3 4" \
+ git rebase -i --root 2>warn.tmp &&
+ test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+ sed -n "1p" warn.tmp >warnl1.tmp &&
+ echo "Warning : some commits may have been dropped accidentally."
>l1.tmp &&
+ test_cmp warnl1.tmp l1.tmp
+'
+
test_done
--
2.4.1.411.g9c4ad60
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html