1# This shell script fragment is sourced by git-rebase to implement 2# its interactive mode. "git rebase --interactive" makes it easy 3# to fix up commits in the middle of a series and rearrange commits. 4# 5# Copyright (c) 2006 Johannes E. Schindelin 6# 7# The original idea comes from Eric W. Biederman, in 8# https://public-inbox.org/git/m1odwkyuf5.fsf_-_@ebiederm.dsl.xmission.com/ 9# 10# The file containing rebase commands, comments, and empty lines. 11# This file is created by "git rebase -i" then edited by the user. As 12# the lines are processed, they are removed from the front of this 13# file and written to the tail of $done. 14todo="$state_dir"/git-rebase-todo 15 16GIT_CHERRY_PICK_HELP="$resolvemsg" 17export GIT_CHERRY_PICK_HELP 18 19comment_char=$(git config --get core.commentchar 2>/dev/null) 20case"$comment_char"in 21''| auto) 22 comment_char="#" 23;; 24?) 25;; 26*) 27 comment_char=$(echo "$comment_char" | cut -c1) 28;; 29esac 30 31orig_reflog_action="$GIT_REFLOG_ACTION" 32 33comment_for_reflog () { 34case"$orig_reflog_action"in 35''|rebase*) 36 GIT_REFLOG_ACTION="rebase -i ($1)" 37export GIT_REFLOG_ACTION 38;; 39esac 40} 41 42append_todo_help () { 43gettext" 44Commands: 45p, pick <commit> = use commit 46r, reword <commit> = use commit, but edit the commit message 47e, edit <commit> = use commit, but stop for amending 48s, squash <commit> = use commit, but meld into previous commit 49f, fixup <commit> = like\"squash\", but discard this commit's log message 50x, exec <command> = run command (the rest of the line) using shell 51d, drop <commit> = remove commit 52l, label <label> = label current HEAD with a name 53t, reset <label> = reset HEAD to a label 54m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] 55. create a merge commit using the original merge commit's 56. message (or the oneline, if no original merge commit was 57. specified). Use -c <commit> to reword the commit message. 58 59These lines can be re-ordered; they are executed from top to bottom. 60"| git stripspace --comment-lines>>"$todo" 61 62iftest$(get_missing_commit_check_level)= error 63then 64gettext" 65Do not remove any line. Use 'drop' explicitly to remove a commit. 66"| git stripspace --comment-lines>>"$todo" 67else 68gettext" 69If you remove a line here THAT COMMIT WILL BE LOST. 70"| git stripspace --comment-lines>>"$todo" 71fi 72} 73 74die_abort () { 75 apply_autostash 76rm-rf"$state_dir" 77 die "$1" 78} 79 80has_action () { 81test -n"$(git stripspace --strip-comments <"$1")" 82} 83 84git_sequence_editor () { 85iftest -z"$GIT_SEQUENCE_EDITOR" 86then 87 GIT_SEQUENCE_EDITOR="$(git config sequence.editor)" 88if[-z"$GIT_SEQUENCE_EDITOR"] 89then 90 GIT_SEQUENCE_EDITOR="$(git var GIT_EDITOR)"||return $? 91fi 92fi 93 94eval"$GIT_SEQUENCE_EDITOR"'"$@"' 95} 96 97expand_todo_ids() { 98 git rebase--helper --expand-ids 99} 100 101collapse_todo_ids() { 102 git rebase--helper --shorten-ids 103} 104 105# Switch to the branch in $into and notify it in the reflog 106checkout_onto () { 107 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout$onto_name" 108 output git checkout $onto|| die_abort "$(gettext "could not detach HEAD")" 109 git update-ref ORIG_HEAD $orig_head 110} 111 112get_missing_commit_check_level () { 113 check_level=$(git config --get rebase.missingCommitsCheck) 114 check_level=${check_level:-ignore} 115# Don't be case sensitive 116printf'%s'"$check_level"|tr'A-Z''a-z' 117} 118 119# Initiate an action. If the cannot be any 120# further action it may exec a command 121# or exit and not return. 122# 123# TODO: Consider a cleaner return model so it 124# never exits and always return 0 if process 125# is complete. 126# 127# Parameter 1 is the action to initiate. 128# 129# Returns 0 if the action was able to complete 130# and if 1 if further processing is required. 131initiate_action () { 132case"$1"in 133continue) 134exec git rebase--helper${force_rebase:+--no-ff} $allow_empty_message \ 135--continue 136;; 137 skip) 138 git rerere clear 139exec git rebase--helper${force_rebase:+--no-ff} $allow_empty_message \ 140--continue 141;; 142 edit-todo) 143 git stripspace --strip-comments<"$todo">"$todo".new 144mv-f"$todo".new "$todo" 145 collapse_todo_ids 146 append_todo_help 147gettext" 148You are editing the todo file of an ongoing interactive rebase. 149To continue rebase after editing, run: 150 git rebase --continue 151 152"| git stripspace --comment-lines>>"$todo" 153 154 git_sequence_editor "$todo"|| 155 die "$(gettext "Could not execute editor")" 156 expand_todo_ids 157 158exit 159;; 160 show-current-patch) 161exec git show REBASE_HEAD -- 162;; 163*) 164return1# continue 165;; 166esac 167} 168 169setup_reflog_action () { 170 comment_for_reflog start 171 172iftest!-z"$switch_to" 173then 174 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout$switch_to" 175 output git checkout "$switch_to"--|| 176 die "$(eval_gettext "Could not checkout \$switch_to")" 177 178 comment_for_reflog start 179fi 180} 181 182init_basic_state () { 183 orig_head=$(git rev-parse --verify HEAD)|| die "$(gettext "No HEAD?")" 184mkdir-p"$state_dir"|| die "$(eval_gettext "Could not create temporary \$state_dir")" 185rm-f"$(git rev-parse --git-path REBASE_HEAD)" 186 187: >"$state_dir"/interactive || die "$(gettext "Could not mark as interactive")" 188 write_basic_state 189} 190 191init_revisions_and_shortrevisions () { 192 shorthead=$(git rev-parse --short $orig_head) 193 shortonto=$(git rev-parse --short $onto) 194iftest -z"$rebase_root" 195# this is now equivalent to ! -z "$upstream" 196then 197 shortupstream=$(git rev-parse --short $upstream) 198 revisions=$upstream...$orig_head 199 shortrevisions=$shortupstream..$shorthead 200else 201 revisions=$onto...$orig_head 202 shortrevisions=$shorthead 203test -z"$squash_onto"|| 204echo"$squash_onto">"$state_dir"/squash-onto 205fi 206} 207 208complete_action() { 209test -s"$todo"||echo noop >>"$todo" 210test -z"$autosquash"|| git rebase--helper --rearrange-squash||exit 211test -n"$cmd"&& git rebase--helper --add-exec-commands"$cmd" 212 213 todocount=$(git stripspace --strip-comments <"$todo" | wc -l) 214 todocount=${todocount##* } 215 216cat>>"$todo"<<EOF 217 218$comment_char$(eval_ngettext \ 219 "Rebase \$shortrevisionsonto \$shortonto(\$todocountcommand)" \ 220 "Rebase \$shortrevisionsonto \$shortonto(\$todocountcommands)" \ 221 "$todocount") 222EOF 223 append_todo_help 224gettext" 225 However, if you remove everything, the rebase will be aborted. 226 227 "| git stripspace --comment-lines>>"$todo" 228 229iftest -z"$keep_empty" 230then 231printf'%s\n'"$comment_char$(gettext "Note that empty commits are commented out")">>"$todo" 232fi 233 234 235 has_action "$todo"|| 236return2 237 238cp"$todo""$todo".backup 239 collapse_todo_ids 240 git_sequence_editor "$todo"|| 241 die_abort "$(gettext "Could not execute editor")" 242 243 has_action "$todo"|| 244return2 245 246 git rebase--helper --check-todo-list|| { 247 ret=$? 248 checkout_onto 249exit$ret 250} 251 252 expand_todo_ids 253 254test -n"$force_rebase"|| 255 onto="$(git rebase--helper --skip-unnecessary-picks)"|| 256 die "Could not skip unnecessary pick commands" 257 258 checkout_onto 259 require_clean_work_tree "rebase" 260exec git rebase--helper${force_rebase:+--no-ff} $allow_empty_message \ 261--continue 262} 263 264git_rebase__interactive () { 265 initiate_action "$action" 266 ret=$? 267iftest$ret=0;then 268return0 269fi 270 271 setup_reflog_action 272 init_basic_state 273 274 init_revisions_and_shortrevisions 275 276 git rebase--helper --make-script${keep_empty:+--keep-empty} \ 277${rebase_merges:+--rebase-merges} \ 278${rebase_cousins:+--rebase-cousins} \ 279$revisions ${restrict_revision+^$restrict_revision}>"$todo"|| 280 die "$(gettext "Could not generate todo list")" 281 282 complete_action 283}