refactor userdiff textconv code
[gitweb.git] / git-rebase--interactive.sh
index b0d757db5dbb97d91014b22e34938ca0764dd4ef..39f8d73dfa4377922fd8ebc406643d73338916d0 100755 (executable)
@@ -38,6 +38,7 @@ DONE="$DOTEST"/done
 MSG="$DOTEST"/message
 SQUASH_MSG="$DOTEST"/message-squash
 REWRITTEN="$DOTEST"/rewritten
+DROPPED="$DOTEST"/dropped
 PRESERVE_MERGES=
 STRATEGY=
 ONTO=
@@ -182,8 +183,12 @@ pick_one_preserving_merges () {
 
        # rewrite parents; if none were rewritten, we can fast-forward.
        new_parents=
-       for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
+       pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)"
+       while [ "$pend" != "" ]
        do
+               p=$(expr "$pend" : ' \([^ ]*\)')
+               pend="${pend# $p}"
+
                if test -f "$REWRITTEN"/$p
                then
                        new_p=$(cat "$REWRITTEN"/$p)
@@ -196,7 +201,13 @@ pick_one_preserving_merges () {
                                ;;
                        esac
                else
-                       new_parents="$new_parents $p"
+                       if test -f "$DROPPED"/$p
+                       then
+                               fast_forward=f
+                               pend=" $(cat "$DROPPED"/$p)$pend"
+                       else
+                               new_parents="$new_parents $p"
+                       fi
                fi
        done
        case $fast_forward in
@@ -280,7 +291,7 @@ do_next () {
                "$DOTEST"/amend || exit
        read command sha1 rest < "$TODO"
        case "$command" in
-       '#'*|'')
+       '#'*|''|noop)
                mark_action_done
                ;;
        pick|p)
@@ -317,23 +328,28 @@ do_next () {
 
                mark_action_done
                make_squash_message $sha1 > "$MSG"
+               failed=f
+               author_script=$(get_author_ident_from_commit HEAD)
+               output git reset --soft HEAD^
+               pick_one -n $sha1 || failed=t
                case "$(peek_next_command)" in
                squash|s)
                        EDIT_COMMIT=
                        USE_OUTPUT=output
+                       MSG_OPT=-F
+                       MSG_FILE="$MSG"
                        cp "$MSG" "$SQUASH_MSG"
                        ;;
                *)
                        EDIT_COMMIT=-e
                        USE_OUTPUT=
+                       MSG_OPT=
+                       MSG_FILE=
                        rm -f "$SQUASH_MSG" || exit
+                       cp "$MSG" "$GIT_DIR"/SQUASH_MSG
+                       rm -f "$GIT_DIR"/MERGE_MSG || exit
                        ;;
                esac
-
-               failed=f
-               author_script=$(get_author_ident_from_commit HEAD)
-               output git reset --soft HEAD^
-               pick_one -n $sha1 || failed=t
                echo "$author_script" > "$DOTEST"/author-script
                if test $failed = f
                then
@@ -342,7 +358,7 @@ do_next () {
                        GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
                        GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
                        GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
-                       $USE_OUTPUT git commit --no-verify -F "$MSG" $EDIT_COMMIT || failed=t
+                       $USE_OUTPUT git commit --no-verify $MSG_OPT "$MSG_FILE" $EDIT_COMMIT || failed=t
                fi
                if test $failed = t
                then
@@ -587,6 +603,7 @@ first and then run 'git rebase --continue' again."
                        --abbrev=7 --reverse --left-right --cherry-pick \
                        $UPSTREAM...$HEAD | \
                        sed -n "s/^>/pick /p" > "$TODO"
+               test -s "$TODO" || echo noop >> "$TODO"
                cat >> "$TODO" << EOF
 
 # Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
@@ -601,6 +618,28 @@ first and then run 'git rebase --continue' again."
 #
 EOF
 
+               # Watch for commits that been dropped by --cherry-pick
+               if test t = "$PRESERVE_MERGES"
+               then
+                       mkdir "$DROPPED"
+                       # drop the --cherry-pick parameter this time
+                       git rev-list $MERGES_OPTION --abbrev-commit \
+                               --abbrev=7 $UPSTREAM...$HEAD --left-right | \
+                               sed -n "s/^>//p" | while read rev
+                       do
+                               grep --quiet "$rev" "$TODO"
+                               if [ $? -ne 0 ]
+                               then
+                                       # Use -f2 because if rev-list is telling this commit is not
+                                       # worthwhile, we don't want to track its multiple heads,
+                                       # just the history of its first-parent for others that will
+                                       # be rebasing on top of us
+                                       full=$(git rev-parse $rev)
+                                       git rev-list --parents -1 $rev | cut -d' ' -f2 > "$DROPPED"/$full
+                               fi
+                       done
+               fi
+
                has_action "$TODO" ||
                        die_abort "Nothing to do"