]> git.ipfire.org Git - thirdparty/git.git/blame - git-rebase--interactive.sh
t5318: avoid unnecessary command substitutions
[thirdparty/git.git] / git-rebase--interactive.sh
CommitLineData
11d62145
JN
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.
1b1dce4b
JS
4#
5# Copyright (c) 2006 Johannes E. Schindelin
1b1dce4b
JS
6#
7# The original idea comes from Eric W. Biederman, in
5840eb9d 8# https://public-inbox.org/git/m1odwkyuf5.fsf_-_@ebiederm.dsl.xmission.com/
572a7c52 9#
80883bb3
MH
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
6bb4e485 13# file and written to the tail of $done.
431b7e78 14todo="$state_dir"/git-rebase-todo
80883bb3 15
89c7ae9c 16GIT_CHERRY_PICK_HELP="$resolvemsg"
804c7174
WC
17export GIT_CHERRY_PICK_HELP
18
882cd237
JS
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
180bad3d 30
6bb4e485 31orig_reflog_action="$GIT_REFLOG_ACTION"
1b1dce4b
JS
32
33comment_for_reflog () {
6bb4e485 34 case "$orig_reflog_action" in
1b1dce4b
JS
35 ''|rebase*)
36 GIT_REFLOG_ACTION="rebase -i ($1)"
37 export GIT_REFLOG_ACTION
376ccb8c 38 ;;
1b1dce4b
JS
39 esac
40}
41
fcc5ef1c 42append_todo_help () {
b8fc9e43 43 gettext "
180bad3d 44Commands:
f431d73d
SB
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
35d515b5 50x, exec <command> = run command (the rest of the line) using shell
f431d73d 51d, drop <commit> = remove commit
9055e401
JS
52l, label <label> = label current HEAD with a name
53t, reset <label> = reset HEAD to a label
4c68e7dd
JS
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.
180bad3d
JK
58
59These lines can be re-ordered; they are executed from top to bottom.
b8fc9e43 60" | git stripspace --comment-lines >>"$todo"
180bad3d 61
37079959
GR
62 if test $(get_missing_commit_check_level) = error
63 then
b8fc9e43 64 gettext "
37079959 65Do not remove any line. Use 'drop' explicitly to remove a commit.
b8fc9e43 66" | git stripspace --comment-lines >>"$todo"
37079959 67 else
b8fc9e43 68 gettext "
180bad3d 69If you remove a line here THAT COMMIT WILL BE LOST.
b8fc9e43 70" | git stripspace --comment-lines >>"$todo"
37079959 71 fi
fcc5ef1c
AW
72}
73
c54b7817 74die_abort () {
33ba9c64 75 apply_autostash
431b7e78 76 rm -rf "$state_dir"
c54b7817
JS
77 die "$1"
78}
79
376ccb8c 80has_action () {
180bad3d 81 test -n "$(git stripspace --strip-comments <"$1")"
376ccb8c
JS
82}
83
821881d8
PO
84git_sequence_editor () {
85 if test -z "$GIT_SEQUENCE_EDITOR"
86 then
87 GIT_SEQUENCE_EDITOR="$(git config sequence.editor)"
88 if [ -z "$GIT_SEQUENCE_EDITOR" ]
89 then
90 GIT_SEQUENCE_EDITOR="$(git var GIT_EDITOR)" || return $?
91 fi
92 fi
93
94 eval "$GIT_SEQUENCE_EDITOR" '"$@"'
95}
96
75c69766 97expand_todo_ids() {
3546c8d9 98 git rebase--helper --expand-ids
75c69766
JH
99}
100
101collapse_todo_ids() {
3546c8d9 102 git rebase--helper --shorten-ids
f59baa50
NS
103}
104
37079959
GR
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"
9588c52b 108 output git checkout $onto || die_abort "$(gettext "could not detach HEAD")"
37079959
GR
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
116 printf '%s' "$check_level" | tr 'A-Z' 'a-z'
117}
118
27c499bf
WS
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 () {
132 case "$1" in
d48f97aa 133 continue)
9384c0ca
AG
134 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
135 --continue
d48f97aa
WS
136 ;;
137 skip)
138 git rerere clear
9384c0ca
AG
139 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
140 --continue
d48f97aa
WS
141 ;;
142 edit-todo)
143 git stripspace --strip-comments <"$todo" >"$todo".new
144 mv -f "$todo".new "$todo"
145 collapse_todo_ids
146 append_todo_help
147 gettext "
180bad3d
JK
148You are editing the todo file of an ongoing interactive rebase.
149To continue rebase after editing, run:
150 git rebase --continue
151
b8fc9e43 152" | git stripspace --comment-lines >>"$todo"
eb9a7cb4 153
d48f97aa
WS
154 git_sequence_editor "$todo" ||
155 die "$(gettext "Could not execute editor")"
156 expand_todo_ids
34262322 157
d48f97aa
WS
158 exit
159 ;;
160 show-current-patch)
161 exec git show REBASE_HEAD --
162 ;;
27c499bf
WS
163 *)
164 return 1 # continue
165 ;;
d48f97aa 166 esac
27c499bf 167}
26cd160c 168
27c499bf 169setup_reflog_action () {
26cd160c 170 comment_for_reflog start
34262322 171
d48f97aa 172 if test ! -z "$switch_to"
34262322 173 then
d48f97aa
WS
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
34262322 179 fi
27c499bf 180}
62db5247 181
27c499bf 182init_basic_state () {
d48f97aa
WS
183 orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")"
184 mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
185 rm -f "$(git rev-parse --git-path REBASE_HEAD)"
90e1818f 186
d48f97aa
WS
187 : > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
188 write_basic_state
27c499bf
WS
189}
190
191init_revisions_and_shortrevisions () {
192 shorthead=$(git rev-parse --short $orig_head)
193 shortonto=$(git rev-parse --short $onto)
194 if test -z "$rebase_root"
195 # this is now equivalent to ! -z "$upstream"
196 then
197 shortupstream=$(git rev-parse --short $upstream)
198 revisions=$upstream...$orig_head
199 shortrevisions=$shortupstream..$shorthead
200 else
201 revisions=$onto...$orig_head
202 shortrevisions=$shorthead
21d0764c
JS
203 test -z "$squash_onto" ||
204 echo "$squash_onto" >"$state_dir"/squash-onto
27c499bf
WS
205 fi
206}
207
208complete_action() {
209 test -s "$todo" || echo noop >> "$todo"
210 test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
211 test -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 \$shortrevisions onto \$shortonto (\$todocount command)" \
220 "Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
221 "$todocount")
222EOF
223 append_todo_help
224 gettext "
225 However, if you remove everything, the rebase will be aborted.
226
227 " | git stripspace --comment-lines >>"$todo"
228
229 if test -z "$keep_empty"
230 then
231 printf '%s\n' "$comment_char $(gettext "Note that empty commits are commented out")" >>"$todo"
232 fi
233
234
235 has_action "$todo" ||
236 return 2
237
238 cp "$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" ||
244 return 2
245
246 git rebase--helper --check-todo-list || {
247 ret=$?
248 checkout_onto
249 exit $ret
250 }
251
252 expand_todo_ids
253
9384c0ca 254 test -n "$force_rebase" ||
27c499bf
WS
255 onto="$(git rebase--helper --skip-unnecessary-picks)" ||
256 die "Could not skip unnecessary pick commands"
257
258 checkout_onto
9384c0ca
AG
259 require_clean_work_tree "rebase"
260 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
261 --continue
27c499bf
WS
262}
263
264git_rebase__interactive () {
265 initiate_action "$action"
266 ret=$?
267 if test $ret = 0; then
268 return 0
269 fi
270
271 setup_reflog_action
272 init_basic_state
273
27c499bf
WS
274 init_revisions_and_shortrevisions
275
c04549b2 276 git rebase--helper --make-script ${keep_empty:+--keep-empty} \
8f6aed71 277 ${rebase_merges:+--rebase-merges} \
7543f6f4 278 ${rebase_cousins:+--rebase-cousins} \
c04549b2
WS
279 $revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
280 die "$(gettext "Could not generate todo list")"
950b487c
WS
281
282 complete_action
283}