rebase -i: introduce the 'break' command
The 'edit' command can be used to cherry-pick a commit and then immediately drop out of the interactive rebase, with exit code 0, to let the user amend the commit, or test it, or look around. Sometimes this functionality would come in handy *without* cherry-picking a commit, e.g. to interrupt the interactive rebase even before cherry-picking a commit, or immediately after an 'exec' or a 'merge'. This commit introduces that functionality, as the spanking new 'break' command. Suggested-by: Stefan Beller <sbeller@google.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Johannes Schindelin committed
Oct 12, 2018 at 06:14 UTC
71f82465b1c9546a09c442c3c9aa22ecbb76f820
5 files changed
+37
-2
Documentation/git-rebase.txt
+3
@@ -561,6 +561,9 @@ By replacing the command "pick" with the command "edit", you can tell
561
the files and/or the commit message, amend the commit, and continue
562
rebasing.
563
564
+To interrupt the rebase (just like an "edit" command would do, but without
565
+cherry-picking any commit first), use the "break" command.
566
+
567
If you just want to edit the commit message for a commit, replace the
568
command "pick" with the command "reword".
569
rebase-interactive.c
+1
@@ -14,6 +14,7 @@ void append_todo_help(unsigned edit_todo, unsigned keep_empty,
14
"s, squash <commit> = use commit, but meld into previous commit\n"
15
"f, fixup <commit> = like \"squash\", but discard this commit's log message\n"
16
"x, exec <command> = run command (the rest of the line) using shell\n"
17
+"b, break = stop here (continue rebase later with 'git rebase --continue')\n"
18
"d, drop <commit> = remove commit\n"
19
"l, label <label> = label current HEAD with a name\n"
20
"t, reset <label> = reset HEAD to a label\n"
sequencer.c
+23
-1
@@ -1416,6 +1416,7 @@ enum todo_command {
1416
TODO_SQUASH,
1417
/* commands that do something else than handling a single commit */
1418
TODO_EXEC,
1419
+ TODO_BREAK,
1420
TODO_LABEL,
1421
TODO_RESET,
1422
TODO_MERGE,
@@ -1437,6 +1438,7 @@ static struct {
1438
{ 'f', "fixup" },
1439
{ 's', "squash" },
1440
{ 'x', "exec" },
1441
+ { 'b', "break" },
1442
{ 'l', "label" },
1443
{ 't', "reset" },
1444
{ 'm', "merge" },
@@ -1964,7 +1966,7 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
1966
padding = strspn(bol, " \t");
1967
bol += padding;
1968
1967
- if (item->command == TODO_NOOP) {
1969
+ if (item->command == TODO_NOOP || item->command == TODO_BREAK) {
1970
if (bol != eol)
1971
return error(_("%s does not accept arguments: '%s'"),
1972
command_to_string(item->command), bol);
@@ -3247,6 +3249,23 @@ static int checkout_onto(struct replay_opts *opts,
3249
return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
3250
}
3251
3252
+static int stopped_at_head(void)
3253
+{
3254
+ struct object_id head;
3255
+ struct commit *commit;
3256
+ struct commit_message message;
3257
+
3258
+ if (get_oid("HEAD", &head) || !(commit = lookup_commit(&head)) ||
3259
+ parse_commit(commit) || get_message(commit, &message))
3260
+ fprintf(stderr, _("Stopped at HEAD\n"));
3261
+ else {
3262
+ fprintf(stderr, _("Stopped at %s\n"), message.label);
3263
+ free_message(commit, &message);
3264
+ }
3265
+ return 0;
3266
+
3267
+}
3268
+
3269
static const char rescheduled_advice[] =
3270
N_("Could not execute the todo command\n"
3271
"\n"
@@ -3293,6 +3312,9 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
3312
unlink(rebase_path_stopped_sha());
3313
unlink(rebase_path_amend());
3314
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
3315
+
3316
+ if (item->command == TODO_BREAK)
3317
+ return stopped_at_head();
3318
}
3319
if (item->command <= TODO_SQUASH) {
3320
if (is_rebase_i(opts))
t/lib-rebase.sh
+1
-1
@@ -49,7 +49,7 @@ set_fake_editor () {
49
case $line in
50
squash|fixup|edit|reword|drop)
51
action="$line";;
52
- exec*)
52
+ exec*|break)
53
echo "$line" | sed 's/_/ /g' >> "$1";;
54
"#")
55
echo '# comment' >> "$1";;
t/t3418-rebase-continue.sh
+9
@@ -239,5 +239,14 @@ test_rerere_autoupdate -m
239
GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR
240
test_rerere_autoupdate -i
241
test_rerere_autoupdate --preserve-merges
242
+unset GIT_SEQUENCE_EDITOR
243
+
244
+test_expect_success 'the todo command "break" works' '
245
+ rm -f execed &&
246
+ FAKE_LINES="break exec_>execed" git rebase -i HEAD &&
247
+ test_path_is_missing execed &&
248
+ git rebase --continue &&
249
+ test_path_is_file execed
250
+'
251
252
test_done