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.checkLevel.
Add the configuration variable rebase.checkLevel.
- 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.checkLevel defaults to "ignore".
Signed-off-by: Galan Rémi <[email protected]>
---
Documentation/config.txt | 9 ++++
Documentation/git-rebase.txt | 6 +++
git-rebase--interactive.sh | 105 ++++++++++++++++++++++++++++++++++++++++++
t/t3404-rebase-interactive.sh | 10 +++-
4 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5f76e8c..e2e5554 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2160,6 +2160,15 @@ rebase.autoStash::
successful rebase might result in non-trivial conflicts.
Defaults to false.
+rebase.checkLevel::
+ If set to "warn", git rebase -i will print a warning if some
+ commits are removed (i.e. a line was deleted) or if some
+ commits appear more than one time (e.g. the same commit is
+ picked twice), however the rebase will still proceed. If set
+ to "error", it will print the previous warnings 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..d348ca2 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.checkLevel::
+ If set to "warn" print warnings about removed commits and
+ duplicated 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 2882276..58da6ee 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -837,6 +837,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.checkLevel)
+ 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.checkLevel 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.checkLevel 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
@@ -1079,6 +1182,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 1bad068..d3a9ed5 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1103,7 +1103,6 @@ test_expect_success 'rebase -i commits that overwrite
untracked files (no ff)' '
'
test_expect_success 'drop' '
- git checkout master &&
test_when_finished "git checkout master" &&
git checkout -b dropBranchTest master &&
set_fake_editor &&
@@ -1113,4 +1112,13 @@ test_expect_success 'drop' '
test A = $(git cat-file commit HEAD^^ | sed -ne \$p)
'
+test_expect_success 'rebase -i respects rebase.checkLevel' '
+ test_config rebase.checkLevel error &&
+ test_when_finished "git checkout master" &&
+ 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_done
--
2.4.1.363.g9535a9c
--
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