X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=git-rebase--interactive.sh;h=6566d319aa121fc8f89fff28d0169fd9a1723537;hb=712d2c7dd893212756c21787fc12d6f71327e167;hp=0f04f36eba091653f53511acd4c6d978d074c5c6;hpb=8f9bfb64c5d5179cc7439715379077875248c4ab;p=git.git diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh old mode 100755 new mode 100644 index 0f04f36eb..6566d319a --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -12,22 +12,20 @@ . git-sh-setup -dotest="$GIT_DIR/rebase-merge" - # The file containing rebase commands, comments, and empty lines. # This file is created by "git rebase -i" then edited by the user. As # the lines are processed, they are removed from the front of this # file and written to the tail of $done. -todo="$dotest"/git-rebase-todo +todo="$state_dir"/git-rebase-todo # The rebase command lines that have already been processed. A line # is moved here when it is first handled, before any associated user # actions. -done="$dotest"/done +done="$state_dir"/done # The commit message that is planned to be used for any changes that # need to be committed following a user interaction. -msg="$dotest"/message +msg="$state_dir"/message # The file into which is accumulated the suggested commit message for # squash/fixup commands. When the first of a series of squash/fixups @@ -42,14 +40,14 @@ msg="$dotest"/message # written to the file so far (including the initial "pick" commit). # Each time that a commit message is processed, this line is read and # updated. It is deleted just before the combined commit is made. -squash_msg="$dotest"/message-squash +squash_msg="$state_dir"/message-squash # If the current series of squash/fixups has not yet included a squash # command, then this file exists and holds the commit message of the # original "pick" commit. (If the series ends without a "squash" # command, then this can be used as the commit message of the combined # commit without opening the editor.) -fixup_msg="$dotest"/message-fixup +fixup_msg="$state_dir"/message-fixup # $rewritten is the name of a directory containing files for each # commit that is reachable by at least one merge base of $head and @@ -57,14 +55,14 @@ fixup_msg="$dotest"/message-fixup # might be. This ensures that commits on merged, but otherwise # unrelated side branches are left alone. (Think "X" in the man page's # example.) -rewritten="$dotest"/rewritten +rewritten="$state_dir"/rewritten -dropped="$dotest"/dropped +dropped="$state_dir"/dropped # A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and # GIT_AUTHOR_DATE that will be used for the commit that is currently # being rebased. -author_script="$dotest"/author-script +author_script="$state_dir"/author-script # When an "edit" rebase command is being processed, the SHA1 of the # commit to be edited is recorded in this file. When "git rebase @@ -72,55 +70,27 @@ author_script="$dotest"/author-script # will be amended to the HEAD commit, but only provided the HEAD # commit is still the commit to be edited. When any other rebase # command is processed, this file is deleted. -amend="$dotest"/amend +amend="$state_dir"/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 +rewritten_list="$state_dir"/rewritten-list +rewritten_pending="$state_dir"/rewritten-pending -GIT_CHERRY_PICK_HELP="\ -hint: after resolving the conflicts, mark the corrected paths -hint: with 'git add ' and run 'git rebase --continue'" +GIT_CHERRY_PICK_HELP="$resolvemsg" export GIT_CHERRY_PICK_HELP warn () { printf '%s\n' "$*" >&2 } -output () { - case "$verbose" in - '') - output=$("$@" 2>&1 ) - status=$? - test $status != 0 && printf "%s\n" "$output" - return $status - ;; - *) - "$@" - ;; - esac -} - # Output the commit message for the specified commit. commit_message () { git cat-file commit "$1" | sed "1,/^$/d" } -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 -} - - orig_reflog_action="$GIT_REFLOG_ACTION" comment_for_reflog () { @@ -159,7 +129,7 @@ make_patch () { *) echo "Root commit" ;; - esac > "$dotest"/patch + esac > "$state_dir"/patch test -f "$msg" || commit_message "$1" > "$msg" test -f "$author_script" || @@ -167,14 +137,14 @@ make_patch () { } die_with_patch () { - echo "$1" > "$dotest"/stopped-sha + echo "$1" > "$state_dir"/stopped-sha make_patch "$1" git rerere die "$2" } die_abort () { - rm -rf "$dotest" + rm -rf "$state_dir" die "$1" } @@ -198,11 +168,6 @@ pick_one () { output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" test -d "$rewritten" && pick_one_preserving_merges "$@" && return - if test -n "$rebase_root" - then - output git cherry-pick "$@" - return - fi output git cherry-pick $ff "$@" } @@ -219,20 +184,20 @@ pick_one_preserving_merges () { esac sha1=$(git rev-parse $sha1) - if test -f "$dotest"/current-commit + if test -f "$state_dir"/current-commit then if test "$fast_forward" = t then while read current_commit do git rev-parse HEAD > "$rewritten"/$current_commit - done <"$dotest"/current-commit - rm "$dotest"/current-commit || + done <"$state_dir"/current-commit + rm "$state_dir"/current-commit || die "Cannot write current commit's replacement sha1" fi fi - echo $sha1 >> "$dotest"/current-commit + echo $sha1 >> "$state_dir"/current-commit # rewrite parents; if none were rewritten, we can fast-forward. new_parents= @@ -439,7 +404,7 @@ do_next () { mark_action_done pick_one $sha1 || die_with_patch $sha1 "Could not apply $sha1... $rest" - echo "$sha1" > "$dotest"/stopped-sha + echo "$sha1" > "$state_dir"/stopped-sha make_patch $sha1 git rev-parse --verify HEAD > "$amend" warn "Stopped at $sha1... $rest" @@ -504,7 +469,7 @@ do_next () { printf 'Executing: %s\n' "$rest" # "exec" command doesn't take a sha1 in the todo-list. # => can't just use $sha1 here. - git rev-parse --verify HEAD > "$dotest"/stopped-sha + git rev-parse --verify HEAD > "$state_dir"/stopped-sha ${SHELL:-@SHELL_PATH@} -c "$rest" # Actual execution status=$? if test "$status" -ne 0 @@ -539,19 +504,17 @@ do_next () { test -s "$todo" && return comment_for_reflog finish && - headname=$(cat "$dotest"/head-name) && - oldhead=$(cat "$dotest"/head) && - shortonto=$(git rev-parse --short $(cat "$dotest"/onto)) && + shortonto=$(git rev-parse --short $onto) && newhead=$(git rev-parse HEAD) && - case $headname in + case $head_name in refs/*) - message="$GIT_REFLOG_ACTION: $headname onto $shortonto" && - git update-ref -m "$message" $headname $newhead $oldhead && - git symbolic-ref HEAD $headname + message="$GIT_REFLOG_ACTION: $head_name onto $shortonto" && + git update-ref -m "$message" $head_name $newhead $orig_head && + git symbolic-ref HEAD $head_name ;; esac && { - test ! -f "$dotest"/verbose || - git diff-tree --stat $(cat "$dotest"/head)..HEAD + test ! -f "$state_dir"/verbose || + git diff-tree --stat $orig_head..HEAD } && { test -s "$rewritten_list" && @@ -563,9 +526,9 @@ do_next () { "$GIT_DIR"/hooks/post-rewrite rebase < "$rewritten_list" true # we don't care if this hook failed fi && - rm -rf "$dotest" && + rm -rf "$state_dir" && git gc --auto && - warn "Successfully rebased and updated $headname." + warn "Successfully rebased and updated $head_name." exit } @@ -614,13 +577,6 @@ skip_unnecessary_picks () { die "Could not skip unnecessary pick commands" } -get_saved_options () { - test -d "$rewritten" && preserve_merges=t - test -f "$dotest"/strategy && strategy="$(cat "$dotest"/strategy)" - test -f "$dotest"/verbose && verbose=t - test -f "$dotest"/rebase-root && rebase_root=t -} - # Rearrange the todo list that has both "pick sha1 msg" and # "pick sha1 fixup!/squash! msg" appears in it so that the latter # comes immediately after the former, and change "pick" to @@ -682,37 +638,8 @@ rearrange_squash () { rm -f "$1.sq" "$1.rearranged" } -LF=' -' -parse_onto () { - case "$1" in - *...*) - if left=${1%...*} right=${1#*...} && - onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD}) - then - case "$onto" in - ?*"$LF"?* | '') - exit 1 ;; - esac - echo "$onto" - exit 0 - fi - esac - git rev-parse --verify "$1^0" -} - case "$action" in continue) - get_saved_options - comment_for_reflog continue - - # Sanity check - git rev-parse --verify HEAD >/dev/null || - die "Cannot read HEAD" - 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 --ignore-submodules HEAD -- then @@ -737,96 +664,40 @@ first and then run 'git rebase --continue' again." } fi - record_in_rewritten "$(cat "$dotest"/stopped-sha)" + record_in_rewritten "$(cat "$state_dir"/stopped-sha)" require_clean_work_tree "rebase" do_rest ;; -abort) - get_saved_options - comment_for_reflog abort - - git rerere clear - - headname=$(cat "$dotest"/head-name) - head=$(cat "$dotest"/head) - case $headname in - refs/*) - git symbolic-ref HEAD $headname - ;; - esac && - output git reset --hard $head && - rm -rf "$dotest" - exit - ;; skip) - get_saved_options - comment_for_reflog skip - git rerere clear - output git reset --hard && do_rest + do_rest ;; esac -if test -n "$onto" -then - onto=$(parse_onto "$onto") || die "Does not point to a valid commit: $1" -fi - -test -z "$rebase_root" -a $# -ge 1 -a $# -le 2 || -test ! -z "$rebase_root" -a $# -le 1 || usage - git var GIT_COMMITTER_IDENT >/dev/null || die "You need to set your committer info first" -if test -z "$rebase_root" -then - upstream_arg="$1" - upstream=$(git rev-parse --verify "$1") || die "Invalid base" - test -z "$onto" && onto=$upstream - shift -else - upstream= - upstream_arg=--root - test -z "$onto" && - die "You must specify --onto when using --root" -fi -require_clean_work_tree "rebase" "Please commit or stash them." - -run_pre_rebase_hook "$upstream_arg" "$@" - comment_for_reflog start -if test ! -z "$1" +if test ! -z "$switch_to" then - output git checkout "$1" -- || - die "Could not checkout $1" + output git checkout "$switch_to" -- || + die "Could not checkout $switch_to" fi -head=$(git rev-parse --verify HEAD) || die "No HEAD?" -mkdir "$dotest" || die "Could not create temporary $dotest" - -: > "$dotest"/interactive || die "Could not mark as interactive" -git symbolic-ref HEAD > "$dotest"/head-name 2> /dev/null || - echo "detached HEAD" > "$dotest"/head-name +orig_head=$(git rev-parse --verify HEAD) || die "No HEAD?" +mkdir "$state_dir" || die "Could not create temporary $state_dir" -echo $head > "$dotest"/head -case "$rebase_root" in -'') - rm -f "$dotest"/rebase-root ;; -*) - : >"$dotest"/rebase-root ;; -esac -echo $onto > "$dotest"/onto -test -z "$strategy" || echo "$strategy" > "$dotest"/strategy -test t = "$verbose" && : > "$dotest"/verbose +: > "$state_dir"/interactive || die "Could not mark as interactive" +write_basic_state if test t = "$preserve_merges" then if test -z "$rebase_root" then mkdir "$rewritten" && - for c in $(git merge-base --all $head $upstream) + for c in $(git merge-base --all $orig_head $upstream) do echo $onto > "$rewritten"/$c || die "Could not init rewritten commits" @@ -840,21 +711,21 @@ then # parents to rewrite and skipping dropped commits would # prematurely end our probe merges_option= - first_after_upstream="$(git rev-list --reverse --first-parent $upstream..$head | head -n 1)" + first_after_upstream="$(git rev-list --reverse --first-parent $upstream..$orig_head | head -n 1)" else merges_option="--no-merges --cherry-pick" fi -shorthead=$(git rev-parse --short $head) +shorthead=$(git rev-parse --short $orig_head) shortonto=$(git rev-parse --short $onto) if test -z "$rebase_root" # this is now equivalent to ! -z "$upstream" then shortupstream=$(git rev-parse --short $upstream) - revisions=$upstream...$head + revisions=$upstream...$orig_head shortrevisions=$shortupstream..$shorthead else - revisions=$onto...$head + revisions=$onto...$orig_head shortrevisions=$shorthead fi git rev-list $merges_option --pretty=oneline --abbrev-commit \ @@ -895,13 +766,13 @@ then mkdir "$dropped" # Save all non-cherry-picked changes git rev-list $revisions --left-right --cherry-pick | \ - sed -n "s/^>//p" > "$dotest"/not-cherry-picks + sed -n "s/^>//p" > "$state_dir"/not-cherry-picks # Now all commits and note which ones are missing in # not-cherry-picks and hence being dropped git rev-list $revisions | while read rev do - if test -f "$rewritten"/$rev -a "$(sane_grep "$rev" "$dotest"/not-cherry-picks)" = "" + if test -f "$rewritten"/$rev -a "$(sane_grep "$rev" "$state_dir"/not-cherry-picks)" = "" then # Use -f2 because if rev-list is telling us this commit is # not worthwhile, we don't want to track its multiple heads, @@ -947,5 +818,5 @@ has_action "$todo" || test -d "$rewritten" || test -n "$force_rebase" || skip_unnecessary_picks output git checkout $onto || die_abort "could not detach HEAD" -git update-ref ORIG_HEAD $head +git update-ref ORIG_HEAD $orig_head do_rest