Skip to content

Commit

Permalink
Merge branch 'interactive-rebase'
Browse files Browse the repository at this point in the history
This series of branches introduces the git-rebase--helper, a builtin
helping to accelerate the interactive rebase dramatically.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Sep 6, 2016
2 parents 48e43b0 + 2d81aa7 commit 4c6c87c
Show file tree
Hide file tree
Showing 18 changed files with 2,253 additions and 693 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
/git-read-tree
/git-rebase
/git-rebase--am
/git-rebase--helper
/git-rebase--interactive
/git-rebase--merge
/git-receive-pack
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,7 @@ BUILTIN_OBJS += builtin/prune.o
BUILTIN_OBJS += builtin/pull.o
BUILTIN_OBJS += builtin/push.o
BUILTIN_OBJS += builtin/read-tree.o
BUILTIN_OBJS += builtin/rebase--helper.o
BUILTIN_OBJS += builtin/receive-pack.o
BUILTIN_OBJS += builtin/reflog.o
BUILTIN_OBJS += builtin/remote.o
Expand Down
1 change: 1 addition & 0 deletions builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
extern int cmd_pull(int argc, const char **argv, const char *prefix);
extern int cmd_push(int argc, const char **argv, const char *prefix);
extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
extern int cmd_rebase__helper(int argc, const char **argv, const char *prefix);
extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
extern int cmd_reflog(int argc, const char **argv, const char *prefix);
extern int cmd_remote(int argc, const char **argv, const char *prefix);
Expand Down
2 changes: 1 addition & 1 deletion builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ static void determine_whence(struct wt_status *s)
whence = FROM_MERGE;
else if (file_exists(git_path_cherry_pick_head())) {
whence = FROM_CHERRY_PICK;
if (file_exists(git_path(SEQ_DIR)))
if (file_exists(git_path_seq_dir()))
sequencer_in_use = 1;
}
else
Expand Down
71 changes: 3 additions & 68 deletions builtin/pull.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "revision.h"
#include "tempfile.h"
#include "lockfile.h"
#include "wt-status.h"

enum rebase_type {
REBASE_INVALID = -1,
Expand Down Expand Up @@ -325,73 +326,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}

/**
* Returns 1 if there are unstaged changes, 0 otherwise.
*/
static int has_unstaged_changes(const char *prefix)
{
struct rev_info rev_info;
int result;

init_revisions(&rev_info, prefix);
DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);
DIFF_OPT_SET(&rev_info.diffopt, QUICK);
diff_setup_done(&rev_info.diffopt);
result = run_diff_files(&rev_info, 0);
return diff_result_code(&rev_info.diffopt, result);
}

/**
* Returns 1 if there are uncommitted changes, 0 otherwise.
*/
static int has_uncommitted_changes(const char *prefix)
{
struct rev_info rev_info;
int result;

if (is_cache_unborn())
return 0;

init_revisions(&rev_info, prefix);
DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);
DIFF_OPT_SET(&rev_info.diffopt, QUICK);
add_head_to_pending(&rev_info);
diff_setup_done(&rev_info.diffopt);
result = run_diff_index(&rev_info, 1);
return diff_result_code(&rev_info.diffopt, result);
}

/**
* If the work tree has unstaged or uncommitted changes, dies with the
* appropriate message.
*/
static void die_on_unclean_work_tree(const char *prefix)
{
struct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));
int do_die = 0;

hold_locked_index(lock_file, 0);
refresh_cache(REFRESH_QUIET);
update_index_if_able(&the_index, lock_file);
rollback_lock_file(lock_file);

if (has_unstaged_changes(prefix)) {
error(_("Cannot pull with rebase: You have unstaged changes."));
do_die = 1;
}

if (has_uncommitted_changes(prefix)) {
if (do_die)
error(_("Additionally, your index contains uncommitted changes."));
else
error(_("Cannot pull with rebase: Your index contains uncommitted changes."));
do_die = 1;
}

if (do_die)
exit(1);
}

/**
* Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
* into merge_heads.
Expand Down Expand Up @@ -875,7 +809,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
die(_("Updating an unborn branch with changes added to the index."));

if (!autostash)
die_on_unclean_work_tree(prefix);
require_clean_work_tree("pull with rebase",
"Please commit or stash them.", 1, 0);

if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
hashclr(rebase_fork_point);
Expand Down
67 changes: 67 additions & 0 deletions builtin/rebase--helper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "builtin.h"
#include "cache.h"
#include "parse-options.h"
#include "sequencer.h"

static const char * const builtin_rebase_helper_usage[] = {
N_("git rebase--helper [<options>]"),
NULL
};

int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
{
struct replay_opts opts = REPLAY_OPTS_INIT;
int keep_empty = 0;
enum {
CONTINUE = 1, ABORT, MAKE_SCRIPT, SHORTEN_SHA1S, EXPAND_SHA1S,
CHECK_TODO_LIST, SKIP_UNNECESSARY_PICKS, REARRANGE_SQUASH
} command = 0;
struct option options[] = {
OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
OPT_BOOL(0, "keep-empty", &keep_empty, N_("keep empty commits")),
OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
CONTINUE),
OPT_CMDMODE(0, "abort", &command, N_("abort rebase"),
ABORT),
OPT_CMDMODE(0, "make-script", &command,
N_("make rebase script"), MAKE_SCRIPT),
OPT_CMDMODE(0, "shorten-sha1s", &command,
N_("shorten SHA-1s in the todo list"), SHORTEN_SHA1S),
OPT_CMDMODE(0, "expand-sha1s", &command,
N_("expand SHA-1s in the todo list"), EXPAND_SHA1S),
OPT_CMDMODE(0, "check-todo-list", &command,
N_("check the todo list"), CHECK_TODO_LIST),
OPT_CMDMODE(0, "skip-unnecessary-picks", &command,
N_("skip unnecessary picks"), SKIP_UNNECESSARY_PICKS),
OPT_CMDMODE(0, "rearrange-squash", &command,
N_("rearrange fixup/squash lines"), REARRANGE_SQUASH),
OPT_END()
};

git_config(git_default_config, NULL);

opts.action = REPLAY_INTERACTIVE_REBASE;
opts.allow_ff = 1;
opts.allow_empty = 1;

argc = parse_options(argc, argv, NULL, options,
builtin_rebase_helper_usage, PARSE_OPT_KEEP_ARGV0);

if (command == CONTINUE && argc == 1)
return !!sequencer_continue(&opts);
if (command == ABORT && argc == 1)
return !!sequencer_remove_state(&opts);
if (command == MAKE_SCRIPT && argc > 1)
return !!sequencer_make_script(keep_empty, stdout, argc, argv);
if (command == SHORTEN_SHA1S && argc == 1)
return !!transform_todo_ids(1);
if (command == EXPAND_SHA1S && argc == 1)
return !!transform_todo_ids(0);
if (command == CHECK_TODO_LIST && argc == 1)
return !!check_todo_list();
if (command == SKIP_UNNECESSARY_PICKS && argc == 1)
return !!skip_unnecessary_picks();
if (command == REARRANGE_SQUASH && argc == 1)
return !!rearrange_squash();
usage_with_options(builtin_rebase_helper_usage, options);
}
42 changes: 18 additions & 24 deletions builtin/revert.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void verify_opt_compatible(const char *me, const char *base_opt, ...)
die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
}

static void parse_args(int argc, const char **argv, struct replay_opts *opts)
static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
{
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
const char *me = action_name(opts);
Expand Down Expand Up @@ -115,25 +115,15 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
if (opts->keep_redundant_commits)
opts->allow_empty = 1;

/* Set the subcommand */
if (cmd == 'q')
opts->subcommand = REPLAY_REMOVE_STATE;
else if (cmd == 'c')
opts->subcommand = REPLAY_CONTINUE;
else if (cmd == 'a')
opts->subcommand = REPLAY_ROLLBACK;
else
opts->subcommand = REPLAY_NONE;

/* Check for incompatible command line arguments */
if (opts->subcommand != REPLAY_NONE) {
if (cmd) {
char *this_operation;
if (opts->subcommand == REPLAY_REMOVE_STATE)
if (cmd == 'q')
this_operation = "--quit";
else if (opts->subcommand == REPLAY_CONTINUE)
else if (cmd == 'c')
this_operation = "--continue";
else {
assert(opts->subcommand == REPLAY_ROLLBACK);
assert(cmd == 'a');
this_operation = "--abort";
}

Expand All @@ -156,7 +146,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
"--edit", opts->edit,
NULL);

if (opts->subcommand != REPLAY_NONE) {
if (cmd) {
opts->revs = NULL;
} else {
struct setup_revision_opt s_r_opt;
Expand All @@ -174,35 +164,39 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)

if (argc > 1)
usage_with_options(usage_str, options);

if (cmd == 'q')
return sequencer_remove_state(opts);
if (cmd == 'c')
return sequencer_continue(opts);
if (cmd == 'a')
return sequencer_rollback(opts);
return sequencer_pick_revisions(opts);
}

int cmd_revert(int argc, const char **argv, const char *prefix)
{
struct replay_opts opts;
struct replay_opts opts = REPLAY_OPTS_INIT;
int res;

memset(&opts, 0, sizeof(opts));
if (isatty(0))
opts.edit = 1;
opts.action = REPLAY_REVERT;
git_config(git_default_config, NULL);
parse_args(argc, argv, &opts);
res = sequencer_pick_revisions(&opts);
res = run_sequencer(argc, argv, &opts);
if (res < 0)
die(_("revert failed"));
return res;
}

int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
{
struct replay_opts opts;
struct replay_opts opts = REPLAY_OPTS_INIT;
int res;

memset(&opts, 0, sizeof(opts));
opts.action = REPLAY_PICK;
git_config(git_default_config, NULL);
parse_args(argc, argv, &opts);
res = sequencer_pick_revisions(&opts);
res = run_sequencer(argc, argv, &opts);
if (res < 0)
die(_("cherry-pick failed"));
return res;
Expand Down
Loading

0 comments on commit 4c6c87c

Please sign in to comment.