]> asedeno.scripts.mit.edu Git - git.git/blobdiff - git-rebase--interactive.sh
Merge branch 'tr/workflow-doc'
[git.git] / git-rebase--interactive.sh
index 58126bd80cd73993c6cedd548e200c0fa461a8af..86290f63b25f921de5c78b087e111e6b872676fb 100755 (executable)
@@ -26,6 +26,7 @@ i,interactive      always used (no-op)
 continue           continue rebasing process
 abort              abort rebasing process and restore original branch
 skip               skip current patch and continue rebasing process
 continue           continue rebasing process
 abort              abort rebasing process and restore original branch
 skip               skip current patch and continue rebasing process
+no-verify          override pre-rebase hook from stopping the operation
 "
 
 . git-sh-setup
 "
 
 . git-sh-setup
@@ -41,6 +42,7 @@ PRESERVE_MERGES=
 STRATEGY=
 ONTO=
 VERBOSE=
 STRATEGY=
 ONTO=
 VERBOSE=
+OK_TO_SKIP_PRE_REBASE=
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -65,6 +67,17 @@ output () {
        esac
 }
 
        esac
 }
 
+run_pre_rebase_hook () {
+       if test -z "$OK_TO_SKIP_PRE_REBASE" &&
+          test -x "$GIT_DIR/hooks/pre-rebase"
+       then
+               "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
+                       echo >&2 "The pre-rebase hook refused to rebase."
+                       exit 1
+               }
+       fi
+}
+
 require_clean_work_tree () {
        # test if working tree is dirty
        git rev-parse --verify HEAD > /dev/null &&
 require_clean_work_tree () {
        # test if working tree is dirty
        git rev-parse --verify HEAD > /dev/null &&
@@ -165,14 +178,14 @@ pick_one_preserving_merges () {
                die "Cannot write current commit's replacement sha1"
        fi
 
                die "Cannot write current commit's replacement sha1"
        fi
 
+       echo $sha1 > "$DOTEST"/current-commit
+
        # rewrite parents; if none were rewritten, we can fast-forward.
        # rewrite parents; if none were rewritten, we can fast-forward.
-       preserve=t
        new_parents=
        for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
        do
                if test -f "$REWRITTEN"/$p
                then
        new_parents=
        for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
        do
                if test -f "$REWRITTEN"/$p
                then
-                       preserve=f
                        new_p=$(cat "$REWRITTEN"/$p)
                        test $p != $new_p && fast_forward=f
                        case "$new_parents" in
                        new_p=$(cat "$REWRITTEN"/$p)
                        test $p != $new_p && fast_forward=f
                        case "$new_parents" in
@@ -189,7 +202,6 @@ pick_one_preserving_merges () {
        case $fast_forward in
        t)
                output warn "Fast forward to $sha1"
        case $fast_forward in
        t)
                output warn "Fast forward to $sha1"
-               test $preserve = f || echo $sha1 > "$REWRITTEN"/$sha1
                output git reset --hard $sha1 ||
                        die "Cannot fast forward to $sha1"
                ;;
                output git reset --hard $sha1 ||
                        die "Cannot fast forward to $sha1"
                ;;
@@ -201,7 +213,6 @@ pick_one_preserving_merges () {
                output git checkout $first_parent 2> /dev/null ||
                        die "Cannot move HEAD to $first_parent"
 
                output git checkout $first_parent 2> /dev/null ||
                        die "Cannot move HEAD to $first_parent"
 
-               echo $sha1 > "$DOTEST"/current-commit
                case "$new_parents" in
                ' '*' '*)
                        # redo merge
                case "$new_parents" in
                ' '*' '*)
                        # redo merge
@@ -269,7 +280,7 @@ do_next () {
                "$DOTEST"/amend || exit
        read command sha1 rest < "$TODO"
        case "$command" in
                "$DOTEST"/amend || exit
        read command sha1 rest < "$TODO"
        case "$command" in
-       '#'*|'')
+       '#'*|''|noop)
                mark_action_done
                ;;
        pick|p)
                mark_action_done
                ;;
        pick|p)
@@ -286,7 +297,7 @@ do_next () {
                pick_one $sha1 ||
                        die_with_patch $sha1 "Could not apply $sha1... $rest"
                make_patch $sha1
                pick_one $sha1 ||
                        die_with_patch $sha1 "Could not apply $sha1... $rest"
                make_patch $sha1
-               : > "$DOTEST"/amend
+               git rev-parse --verify HEAD > "$DOTEST"/amend
                warn "Stopped at $sha1... $rest"
                warn "You can amend the commit now, with"
                warn
                warn "Stopped at $sha1... $rest"
                warn "You can amend the commit now, with"
                warn
@@ -306,23 +317,28 @@ do_next () {
 
                mark_action_done
                make_squash_message $sha1 > "$MSG"
 
                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
                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=
                        cp "$MSG" "$SQUASH_MSG"
                        ;;
                *)
                        EDIT_COMMIT=-e
                        USE_OUTPUT=
+                       MSG_OPT=
+                       MSG_FILE=
                        rm -f "$SQUASH_MSG" || exit
                        rm -f "$SQUASH_MSG" || exit
+                       cp "$MSG" "$GIT_DIR"/SQUASH_MSG
+                       rm -f "$GIT_DIR"/MERGE_MSG || exit
                        ;;
                esac
                        ;;
                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
                echo "$author_script" > "$DOTEST"/author-script
                if test $failed = f
                then
@@ -331,7 +347,7 @@ do_next () {
                        GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
                        GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
                        GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
                        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
                fi
                if test $failed = t
                then
@@ -408,6 +424,11 @@ get_saved_options () {
 while test $# != 0
 do
        case "$1" in
 while test $# != 0
 do
        case "$1" in
+       --no-verify)
+               OK_TO_SKIP_PRE_REBASE=yes
+               ;;
+       --verify)
+               ;;
        --continue)
                is_standalone "$@" || usage
                get_saved_options
        --continue)
                is_standalone "$@" || usage
                get_saved_options
@@ -429,14 +450,22 @@ do
                else
                        . "$DOTEST"/author-script ||
                                die "Cannot find the author identity"
                else
                        . "$DOTEST"/author-script ||
                                die "Cannot find the author identity"
+                       amend=
                        if test -f "$DOTEST"/amend
                        then
                        if test -f "$DOTEST"/amend
                        then
+                               amend=$(git rev-parse --verify HEAD)
+                               test "$amend" = $(cat "$DOTEST"/amend) ||
+                               die "\
+You have uncommitted changes in your working tree. Please, commit them
+first and then run 'git rebase --continue' again."
                                git reset --soft HEAD^ ||
                                die "Cannot rewind the HEAD"
                        fi
                        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE &&
                                git reset --soft HEAD^ ||
                                die "Cannot rewind the HEAD"
                        fi
                        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE &&
-                       git commit --no-verify -F "$DOTEST"/message -e ||
-                       die "Could not commit staged changes."
+                       git commit --no-verify -F "$DOTEST"/message -e || {
+                               test -n "$amend" && git reset --soft $amend
+                               die "Could not commit staged changes."
+                       }
                fi
 
                require_clean_work_tree
                fi
 
                require_clean_work_tree
@@ -501,6 +530,7 @@ do
                ;;
        --)
                shift
                ;;
        --)
                shift
+               run_pre_rebase_hook ${1+"$@"}
                test $# -eq 1 -o $# -eq 2 || usage
                test -d "$DOTEST" &&
                        die "Interactive rebase already started"
                test $# -eq 1 -o $# -eq 2 || usage
                test -d "$DOTEST" &&
                        die "Interactive rebase already started"
@@ -562,6 +592,7 @@ do
                        --abbrev=7 --reverse --left-right --cherry-pick \
                        $UPSTREAM...$HEAD | \
                        sed -n "s/^>/pick /p" > "$TODO"
                        --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
                cat >> "$TODO" << EOF
 
 # Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO