diff options
Diffstat (limited to 'git-rebase--interactive.sh')
-rwxr-xr-x | git-rebase--interactive.sh | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 3e4fd1456f..2ff211cbaa 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -96,6 +96,13 @@ AUTHOR_SCRIPT="$DOTEST"/author-script # command is processed, this file is deleted. AMEND="$DOTEST"/amend +# For the post-rewrite hook, we make a list of rewritten commits and +# their new sha1s. The rewritten-pending list keeps the sha1s of +# commits that have been processed, but not committed yet, +# e.g. because they are waiting for a 'squash' command. +REWRITTEN_LIST="$DOTEST"/rewritten-list +REWRITTEN_PENDING="$DOTEST"/rewritten-pending + PRESERVE_MERGES= STRATEGY= ONTO= @@ -198,6 +205,7 @@ make_patch () { } die_with_patch () { + echo "$1" > "$DOTEST"/stopped-sha make_patch "$1" git rerere die "$2" @@ -222,8 +230,8 @@ do_with_author () { } pick_one () { - no_ff= - case "$1" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac + ff=--ff + case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" test -d "$REWRITTEN" && pick_one_preserving_merges "$@" && return @@ -232,16 +240,7 @@ pick_one () { output git cherry-pick "$@" return fi - parent_sha1=$(git rev-parse --verify $sha1^) || - die "Could not get the parent of $sha1" - current_sha1=$(git rev-parse --verify HEAD) - if test -z "$no_ff" && test "$current_sha1" = "$parent_sha1" - then - output git reset --hard $sha1 - output warn Fast-forward to $(git rev-parse --short $sha1) - else - output git cherry-pick "$@" - fi + output git cherry-pick $ff "$@" } pick_one_preserving_merges () { @@ -348,6 +347,7 @@ pick_one_preserving_merges () { printf "%s\n" "$msg" > "$GIT_DIR"/MERGE_MSG die_with_patch $sha1 "Error redoing merge $sha1" fi + echo "$sha1 $(git rev-parse HEAD^0)" >> "$REWRITTEN_LIST" ;; *) output git cherry-pick "$@" || @@ -425,6 +425,26 @@ die_failed_squash() { die_with_patch $1 "" } +flush_rewritten_pending() { + test -s "$REWRITTEN_PENDING" || return + newsha1="$(git rev-parse HEAD^0)" + sed "s/$/ $newsha1/" < "$REWRITTEN_PENDING" >> "$REWRITTEN_LIST" + rm -f "$REWRITTEN_PENDING" +} + +record_in_rewritten() { + oldsha1="$(git rev-parse $1)" + echo "$oldsha1" >> "$REWRITTEN_PENDING" + + case "$(peek_next_command)" in + squash|s|fixup|f) + ;; + *) + flush_rewritten_pending + ;; + esac +} + do_next () { rm -f "$MSG" "$AUTHOR_SCRIPT" "$AMEND" || exit read command sha1 rest < "$TODO" @@ -438,6 +458,7 @@ do_next () { mark_action_done pick_one $sha1 || die_with_patch $sha1 "Could not apply $sha1... $rest" + record_in_rewritten $sha1 ;; reword|r) comment_for_reflog reword @@ -445,7 +466,8 @@ do_next () { mark_action_done pick_one $sha1 || die_with_patch $sha1 "Could not apply $sha1... $rest" - git commit --amend + git commit --amend --no-post-rewrite + record_in_rewritten $sha1 ;; edit|e) comment_for_reflog edit @@ -453,6 +475,7 @@ do_next () { mark_action_done pick_one $sha1 || die_with_patch $sha1 "Could not apply $sha1... $rest" + echo "$sha1" > "$DOTEST"/stopped-sha make_patch $sha1 git rev-parse --verify HEAD > "$AMEND" warn "Stopped at $sha1... $rest" @@ -509,6 +532,7 @@ do_next () { rm -f "$SQUASH_MSG" "$FIXUP_MSG" ;; esac + record_in_rewritten $sha1 ;; *) warn "Unknown command: $command $sha1 $rest" @@ -537,6 +561,15 @@ do_next () { test ! -f "$DOTEST"/verbose || git diff-tree --stat $(cat "$DOTEST"/head)..HEAD } && + { + git notes copy --for-rewrite=rebase < "$REWRITTEN_LIST" || + true # we don't care if this copying failed + } && + if test -x "$GIT_DIR"/hooks/post-rewrite && + test -s "$REWRITTEN_LIST"; then + "$GIT_DIR"/hooks/post-rewrite rebase < "$REWRITTEN_LIST" + true # we don't care if this hook failed + fi && rm -rf "$DOTEST" && git gc --auto && warn "Successfully rebased and updated $HEADNAME." @@ -571,7 +604,12 @@ skip_unnecessary_picks () { esac echo "$command${sha1:+ }$sha1${rest:+ }$rest" >&$fd done <"$TODO" >"$TODO.new" 3>>"$DONE" && - mv -f "$TODO".new "$TODO" || + mv -f "$TODO".new "$TODO" && + case "$(peek_next_command)" in + squash|s|fixup|f) + record_in_rewritten "$ONTO" + ;; + esac || die "Could not skip unnecessary pick commands" } @@ -687,6 +725,8 @@ first and then run 'git rebase --continue' again." } fi + record_in_rewritten "$(cat "$DOTEST"/stopped-sha)" + require_clean_work_tree do_rest ;; @@ -783,8 +823,6 @@ first and then run 'git rebase --continue' again." if test ! -z "$1" then - output git show-ref --verify --quiet "refs/heads/$1" || - die "Invalid branchname: $1" output git checkout "$1" || die "Could not checkout $1" fi |