X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-rebase--interactive.sh;h=929d681c4716fa4f6b2947fdb40ad6fbb580bef3;hb=53b543ab8218cede7fb9383298c00dcef663692c;hp=8aa73712ca11f4527f4b8d42bf3a14de2a16c39c;hpb=53b22a9e45161004ff3260782abc4ee2a5b3e730;p=git.git diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 8aa73712c..929d681c4 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -10,14 +10,28 @@ # The original idea comes from Eric W. Biederman, in # http://article.gmane.org/gmane.comp.version-control.git/22407 -USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose] - [--onto ] [])' +OPTIONS_KEEPDASHDASH= +OPTIONS_SPEC="\ +git-rebase [-i] [options] [--] [] +git-rebase [-i] (--continue | --abort | --skip) +-- + Available options are +v,verbose display a diffstat of what changed upstream +onto= rebase onto given branch instead of upstream +p,preserve-merges try to recreate merges instead of ignoring them +s,strategy= use the given merge strategy +m,merge always used (no-op) +i,interactive always used (no-op) + Actions: +continue continue rebasing process +abort abort rebasing process and restore original branch +skip skip current patch and continue rebasing process +" -OPTIONS_SPEC= . git-sh-setup require_work_tree -DOTEST="$GIT_DIR/.dotest-merge" +DOTEST="$GIT_DIR/rebase-merge" TODO="$DOTEST"/git-rebase-todo DONE="$DOTEST"/done MSG="$DOTEST"/message @@ -25,10 +39,8 @@ SQUASH_MSG="$DOTEST"/message-squash REWRITTEN="$DOTEST"/rewritten PRESERVE_MERGES= STRATEGY= +ONTO= VERBOSE= -test -d "$REWRITTEN" && PRESERVE_MERGES=t -test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)" -test -f "$DOTEST"/verbose && VERBOSE=t GIT_CHERRY_PICK_HELP=" After resolving the conflicts, mark the corrected paths with 'git add ', and @@ -56,9 +68,9 @@ output () { require_clean_work_tree () { # test if working tree is dirty git rev-parse --verify HEAD > /dev/null && - git update-index --refresh && - git diff-files --quiet && - git diff-index --cached --quiet HEAD -- || + git update-index --ignore-submodules --refresh && + git diff-files --quiet --ignore-submodules && + git diff-index --cached --quiet HEAD --ignore-submodules -- || die "Working tree is dirty" } @@ -133,7 +145,16 @@ pick_one () { } pick_one_preserving_merges () { - case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac + fast_forward=t + case "$1" in + -n) + fast_forward=f + sha1=$2 + ;; + *) + sha1=$1 + ;; + esac sha1=$(git rev-parse $sha1) if test -f "$DOTEST"/current-commit @@ -144,15 +165,14 @@ pick_one_preserving_merges () { die "Cannot write current commit's replacement sha1" fi + echo $sha1 > "$DOTEST"/current-commit + # rewrite parents; if none were rewritten, we can fast-forward. - fast_forward=t - preserve=t 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 @@ -162,12 +182,15 @@ pick_one_preserving_merges () { new_parents="$new_parents $new_p" ;; esac + else + new_parents="$new_parents $p" fi done 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" ;; f) test "a$1" = a-n && die "Refusing to squash a merge: $sha1" @@ -177,7 +200,6 @@ pick_one_preserving_merges () { 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 @@ -263,7 +285,7 @@ do_next () { die_with_patch $sha1 "Could not apply $sha1... $rest" make_patch $sha1 : > "$DOTEST"/amend - warn + warn "Stopped at $sha1... $rest" warn "You can amend the commit now, with" warn warn " git commit --amend" @@ -366,10 +388,27 @@ do_rest () { done } +# check if no other options are set +is_standalone () { + test $# -eq 2 -a "$2" = '--' && + test -z "$ONTO" && + test -z "$PRESERVE_MERGES" && + test -z "$STRATEGY" && + test -z "$VERBOSE" +} + +get_saved_options () { + test -d "$REWRITTEN" && PRESERVE_MERGES=t + test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)" + test -f "$DOTEST"/verbose && VERBOSE=t +} + while test $# != 0 do case "$1" in --continue) + is_standalone "$@" || usage + get_saved_options comment_for_reflog continue test -d "$DOTEST" || die "No interactive rebase running" @@ -377,11 +416,12 @@ do # Sanity check git rev-parse --verify HEAD >/dev/null || die "Cannot read HEAD" - git update-index --refresh && git diff-files --quiet || + git update-index --ignore-submodules --refresh && + git diff-files --quiet --ignore-submodules || die "Working tree is dirty" # do we have anything to commit? - if git diff-index --cached --quiet HEAD -- + if git diff-index --cached --quiet --ignore-submodules HEAD -- then : Nothing to commit -- skip this else @@ -401,6 +441,8 @@ do do_rest ;; --abort) + is_standalone "$@" || usage + get_saved_options comment_for_reflog abort git rerere clear @@ -418,6 +460,8 @@ do exit ;; --skip) + is_standalone "$@" || usage + get_saved_options comment_for_reflog skip git rerere clear @@ -425,7 +469,7 @@ do output git reset --hard && do_rest ;; - -s|--strategy) + -s) case "$#,$1" in *,*=*) STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; @@ -436,25 +480,26 @@ do shift ;; esac ;; - -m|--merge) + -m) # we use merge anyway ;; - -C*) - die "Interactive rebase uses merge, so $1 does not make sense" - ;; - -v|--verbose) + -v) VERBOSE=t ;; - -p|--preserve-merges) + -p) PRESERVE_MERGES=t ;; - -i|--interactive) + -i) # yeah, we know ;; - ''|-h) - usage + --onto) + shift + ONTO=$(git rev-parse --verify "$1") || + die "Does not point to a valid commit: $1" ;; - *) + --) + shift + test $# -eq 1 -o $# -eq 2 || usage test -d "$DOTEST" && die "Interactive rebase already started" @@ -463,17 +508,11 @@ do comment_for_reflog start - ONTO= - case "$1" in - --onto) - ONTO=$(git rev-parse --verify "$2") || - die "Does not point to a valid commit: $2" - shift; shift - ;; - esac - require_clean_work_tree + UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base" + test -z "$ONTO" && ONTO=$UPSTREAM + if test ! -z "$2" then output git show-ref --verify --quiet "refs/heads/$2" || @@ -483,12 +522,8 @@ do fi HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?" - UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base" - mkdir "$DOTEST" || die "Could not create temporary $DOTEST" - test -z "$ONTO" && ONTO=$UPSTREAM - : > "$DOTEST"/interactive || die "Could not mark as interactive" git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null || echo "detached HEAD" > "$DOTEST"/head-name @@ -530,9 +565,9 @@ do # Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO # # Commands: -# pick = use commit -# edit = use commit, but stop for amending -# squash = use commit, but meld into previous commit +# p, pick = use commit +# e, edit = use commit, but stop for amending +# s, 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. @@ -549,6 +584,7 @@ EOF has_action "$TODO" || die_abort "Nothing to do" + git update-ref ORIG_HEAD $HEAD output git checkout $ONTO && do_rest ;; esac