Code

Add 'git fast-export', the sister of 'git fast-import'
[git.git] / git-rebase--interactive.sh
index 8568a4fd421d7e60512f0dfc37392bded07419b1..e9cd6fd999695daa1c5ba49835f53041d4131f3a 100755 (executable)
@@ -13,6 +13,7 @@
 USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose]
        [--onto <branch>] <upstream> [<branch>])'
 
+OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
 
@@ -52,7 +53,7 @@ require_clean_work_tree () {
        git rev-parse --verify HEAD > /dev/null &&
        git update-index --refresh &&
        git diff-files --quiet &&
-       git diff-index --cached --quiet HEAD ||
+       git diff-index --cached --quiet HEAD -- ||
        die "Working tree is dirty"
 }
 
@@ -80,7 +81,7 @@ mark_action_done () {
 make_patch () {
        parent_sha1=$(git rev-parse --verify "$1"^) ||
                die "Cannot get patch for $1^"
-       git diff "$parent_sha1".."$1" > "$DOTEST"/patch
+       git diff-tree -p "$parent_sha1".."$1" > "$DOTEST"/patch
        test -f "$DOTEST"/message ||
                git cat-file commit "$1" | sed "1,/^$/d" > "$DOTEST"/message
        test -f "$DOTEST"/author-script ||
@@ -110,13 +111,13 @@ pick_one () {
        parent_sha1=$(git rev-parse --verify $sha1^) ||
                die "Could not get the parent of $sha1"
        current_sha1=$(git rev-parse --verify HEAD)
-       if test $no_ff$current_sha1 = $parent_sha1; then
+       if test "$no_ff$current_sha1" = "$parent_sha1"; then
                output git reset --hard $sha1
                test "a$1" = a-n && output git reset --soft $current_sha1
                sha1=$(git rev-parse --short $sha1)
                output warn Fast forward to $sha1
        else
-               output git cherry-pick $STRATEGY "$@"
+               output git cherry-pick "$@"
        fi
 }
 
@@ -172,6 +173,8 @@ pick_one_preserving_merges () {
                        author_script=$(get_author_ident_from_commit $sha1)
                        eval "$author_script"
                        msg="$(git cat-file commit $sha1 | sed -e '1,/^$/d')"
+                       # No point in merging the first parent, that's HEAD
+                       new_parents=${new_parents# $first_parent}
                        # NEEDSWORK: give rerere a chance
                        if ! GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
                                GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
@@ -184,7 +187,7 @@ pick_one_preserving_merges () {
                        fi
                        ;;
                *)
-                       output git cherry-pick $STRATEGY "$@" ||
+                       output git cherry-pick "$@" ||
                                die_with_patch $sha1 "Could not pick $sha1"
                        ;;
                esac
@@ -317,13 +320,18 @@ do_next () {
        else
                NEWHEAD=$(git rev-parse HEAD)
        fi &&
-       message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
-       git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
-       git symbolic-ref HEAD $HEADNAME && {
+       case $HEADNAME in
+       refs/*)
+               message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
+               git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
+               git symbolic-ref HEAD $HEADNAME
+               ;;
+       esac && {
                test ! -f "$DOTEST"/verbose ||
-                       git diff --stat $(cat "$DOTEST"/head)..HEAD
+                       git diff-tree --stat $(cat "$DOTEST"/head)..HEAD
        } &&
        rm -rf "$DOTEST" &&
+       git gc --auto &&
        warn "Successfully rebased and updated $HEADNAME."
 
        exit
@@ -348,7 +356,7 @@ do
                git rev-parse --verify HEAD > /dev/null &&
                git update-index --refresh &&
                git diff-files --quiet &&
-               ! git diff-index --cached --quiet HEAD &&
+               ! git diff-index --cached --quiet HEAD -- &&
                . "$DOTEST"/author-script && {
                        test ! -f "$DOTEST"/amend || git reset --soft HEAD^
                } &&
@@ -365,7 +373,11 @@ do
 
                HEADNAME=$(cat "$DOTEST"/head-name)
                HEAD=$(cat "$DOTEST"/head)
-               git symbolic-ref HEAD $HEADNAME &&
+               case $HEADNAME in
+               refs/*)
+                       git symbolic-ref HEAD $HEADNAME
+                       ;;
+               esac &&
                output git reset --hard $HEAD &&
                rm -rf "$DOTEST"
                exit
@@ -378,10 +390,9 @@ do
                output git reset --hard && do_rest
                ;;
        -s|--strategy)
-               shift
                case "$#,$1" in
                *,*=*)
-                       STRATEGY="-s `expr "z$1" : 'z-[^=]*=\(.*\)'`" ;;
+                       STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
                1,*)
                        usage ;;
                *)
@@ -443,8 +454,8 @@ do
                test -z "$ONTO" && ONTO=$UPSTREAM
 
                : > "$DOTEST"/interactive || die "Could not mark as interactive"
-               git symbolic-ref HEAD > "$DOTEST"/head-name ||
-                       die "Could not get HEAD"
+               git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
+                       echo "detached HEAD" > "$DOTEST"/head-name
 
                echo $HEAD > "$DOTEST"/head
                echo $UPSTREAM > "$DOTEST"/upstream
@@ -474,8 +485,13 @@ do
                SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
                SHORTHEAD=$(git rev-parse --short $HEAD)
                SHORTONTO=$(git rev-parse --short $ONTO)
-               cat > "$TODO" << EOF
-# Rebasing $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
+               git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
+                       --abbrev=7 --reverse --left-right --cherry-pick \
+                       $UPSTREAM...$HEAD | \
+                       sed -n "s/^>/pick /p" > "$TODO"
+               cat >> "$TODO" << EOF
+
+# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
 #
 # Commands:
 #  pick = use commit
@@ -483,12 +499,9 @@ do
 #  squash = use commit, but meld into previous commit
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
+# However, if you remove everything, the rebase will be aborted.
 #
 EOF
-               git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
-                       --abbrev=7 --reverse --left-right --cherry-pick \
-                       $UPSTREAM...$HEAD | \
-                       sed -n "s/^>/pick /p" >> "$TODO"
 
                has_action "$TODO" ||
                        die_abort "Nothing to do"