]> git.ipfire.org Git - thirdparty/git.git/blob - git-rebase--interactive.sh
2defe607f44722661132a5cbb3545a72cbd56127
[thirdparty/git.git] / git-rebase--interactive.sh
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.
14 todo="$state_dir"/git-rebase-todo
15
16 GIT_CHERRY_PICK_HELP="$resolvemsg"
17 export GIT_CHERRY_PICK_HELP
18
19 comment_char=$(git config --get core.commentchar 2>/dev/null)
20 case "$comment_char" in
21 '' | auto)
22 comment_char="#"
23 ;;
24 ?)
25 ;;
26 *)
27 comment_char=$(echo "$comment_char" | cut -c1)
28 ;;
29 esac
30
31 orig_reflog_action="$GIT_REFLOG_ACTION"
32
33 comment_for_reflog () {
34 case "$orig_reflog_action" in
35 ''|rebase*)
36 GIT_REFLOG_ACTION="rebase -i ($1)"
37 export GIT_REFLOG_ACTION
38 ;;
39 esac
40 }
41
42 die_abort () {
43 apply_autostash
44 rm -rf "$state_dir"
45 die "$1"
46 }
47
48 has_action () {
49 test -n "$(git stripspace --strip-comments <"$1")"
50 }
51
52 git_sequence_editor () {
53 if test -z "$GIT_SEQUENCE_EDITOR"
54 then
55 GIT_SEQUENCE_EDITOR="$(git config sequence.editor)"
56 if [ -z "$GIT_SEQUENCE_EDITOR" ]
57 then
58 GIT_SEQUENCE_EDITOR="$(git var GIT_EDITOR)" || return $?
59 fi
60 fi
61
62 eval "$GIT_SEQUENCE_EDITOR" '"$@"'
63 }
64
65 expand_todo_ids() {
66 git rebase--helper --expand-ids
67 }
68
69 collapse_todo_ids() {
70 git rebase--helper --shorten-ids
71 }
72
73 # Switch to the branch in $into and notify it in the reflog
74 checkout_onto () {
75 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
76 output git checkout $onto || die_abort "$(gettext "could not detach HEAD")"
77 git update-ref ORIG_HEAD $orig_head
78 }
79
80 get_missing_commit_check_level () {
81 check_level=$(git config --get rebase.missingCommitsCheck)
82 check_level=${check_level:-ignore}
83 # Don't be case sensitive
84 printf '%s' "$check_level" | tr 'A-Z' 'a-z'
85 }
86
87 # Initiate an action. If the cannot be any
88 # further action it may exec a command
89 # or exit and not return.
90 #
91 # TODO: Consider a cleaner return model so it
92 # never exits and always return 0 if process
93 # is complete.
94 #
95 # Parameter 1 is the action to initiate.
96 #
97 # Returns 0 if the action was able to complete
98 # and if 1 if further processing is required.
99 initiate_action () {
100 case "$1" in
101 continue)
102 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
103 --continue
104 ;;
105 skip)
106 git rerere clear
107 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
108 --continue
109 ;;
110 edit-todo)
111 exec git rebase--helper --edit-todo
112 ;;
113 show-current-patch)
114 exec git show REBASE_HEAD --
115 ;;
116 *)
117 return 1 # continue
118 ;;
119 esac
120 }
121
122 setup_reflog_action () {
123 comment_for_reflog start
124
125 if test ! -z "$switch_to"
126 then
127 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to"
128 output git checkout "$switch_to" -- ||
129 die "$(eval_gettext "Could not checkout \$switch_to")"
130
131 comment_for_reflog start
132 fi
133 }
134
135 init_basic_state () {
136 orig_head=$(git rev-parse --verify HEAD) || die "$(gettext "No HEAD?")"
137 mkdir -p "$state_dir" || die "$(eval_gettext "Could not create temporary \$state_dir")"
138 rm -f "$(git rev-parse --git-path REBASE_HEAD)"
139
140 : > "$state_dir"/interactive || die "$(gettext "Could not mark as interactive")"
141 write_basic_state
142 }
143
144 init_revisions_and_shortrevisions () {
145 shorthead=$(git rev-parse --short $orig_head)
146 shortonto=$(git rev-parse --short $onto)
147 if test -z "$rebase_root"
148 # this is now equivalent to ! -z "$upstream"
149 then
150 shortupstream=$(git rev-parse --short $upstream)
151 revisions=$upstream...$orig_head
152 shortrevisions=$shortupstream..$shorthead
153 else
154 revisions=$onto...$orig_head
155 shortrevisions=$shorthead
156 test -z "$squash_onto" ||
157 echo "$squash_onto" >"$state_dir"/squash-onto
158 fi
159 }
160
161 complete_action() {
162 test -s "$todo" || echo noop >> "$todo"
163 test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
164 test -n "$cmd" && git rebase--helper --add-exec-commands "$cmd"
165
166 todocount=$(git stripspace --strip-comments <"$todo" | wc -l)
167 todocount=${todocount##* }
168
169 cat >>"$todo" <<EOF
170
171 $comment_char $(eval_ngettext \
172 "Rebase \$shortrevisions onto \$shortonto (\$todocount command)" \
173 "Rebase \$shortrevisions onto \$shortonto (\$todocount commands)" \
174 "$todocount")
175 EOF
176 git rebase--helper --append-todo-help ${keep_empty:+--keep-empty}
177
178 has_action "$todo" ||
179 return 2
180
181 cp "$todo" "$todo".backup
182 collapse_todo_ids
183 git_sequence_editor "$todo" ||
184 die_abort "$(gettext "Could not execute editor")"
185
186 has_action "$todo" ||
187 return 2
188
189 git rebase--helper --check-todo-list || {
190 ret=$?
191 checkout_onto
192 exit $ret
193 }
194
195 expand_todo_ids
196
197 test -n "$force_rebase" ||
198 onto="$(git rebase--helper --skip-unnecessary-picks)" ||
199 die "Could not skip unnecessary pick commands"
200
201 checkout_onto
202 require_clean_work_tree "rebase"
203 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
204 --continue
205 }
206
207 git_rebase__interactive () {
208 initiate_action "$action"
209 ret=$?
210 if test $ret = 0; then
211 return 0
212 fi
213
214 setup_reflog_action
215 init_basic_state
216
217 init_revisions_and_shortrevisions
218
219 git rebase--helper --make-script ${keep_empty:+--keep-empty} \
220 ${rebase_merges:+--rebase-merges} \
221 ${rebase_cousins:+--rebase-cousins} \
222 $revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
223 die "$(gettext "Could not generate todo list")"
224
225 complete_action
226 }