From e61d6952c702b3833c17f1f7ff84807fae4e3fe2 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 13 Dec 2018 13:05:14 +0100 Subject: [PATCH 1/2] rebase: teach `reset_head()` to optionally skip the worktree This is what the legacy (scripted) rebase does in `move_to_original_branch`, and we will need this functionality in the next commit. Signed-off-by: Johannes Schindelin --- builtin/rebase.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index 0fbeb5b95c..693cff2e16 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -368,6 +368,7 @@ static void add_var(struct strbuf *buf, const char *name, const char *value) #define RESET_HEAD_DETACH (1<<0) #define RESET_HEAD_HARD (1<<1) +#define RESET_HEAD_REFS_ONLY (1<<2) static int reset_head(struct object_id *oid, const char *action, const char *switch_to_branch, unsigned flags, @@ -375,6 +376,7 @@ static int reset_head(struct object_id *oid, const char *action, { unsigned detach_head = flags & RESET_HEAD_DETACH; unsigned reset_hard = flags & RESET_HEAD_HARD; + unsigned refs_only = flags & RESET_HEAD_REFS_ONLY; struct object_id head_oid; struct tree_desc desc[2] = { { NULL }, { NULL } }; struct lock_file lock = LOCK_INIT; @@ -390,7 +392,7 @@ static int reset_head(struct object_id *oid, const char *action, if (switch_to_branch && !starts_with(switch_to_branch, "refs/")) BUG("Not a fully qualified branch: '%s'", switch_to_branch); - if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) { + if (!refs_only && hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) { ret = -1; goto leave_reset_head; } @@ -403,6 +405,9 @@ static int reset_head(struct object_id *oid, const char *action, if (!oid) oid = &head_oid; + if (flags & RESET_HEAD_REFS_ONLY) + goto reset_head_refs; + memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts)); setup_unpack_trees_porcelain(&unpack_tree_opts, action); unpack_tree_opts.head_idx = 1; @@ -443,6 +448,7 @@ static int reset_head(struct object_id *oid, const char *action, goto leave_reset_head; } +reset_head_refs: reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT); strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase"); prefix_len = msg.len; From 6c0d9e5685b8cf2097283b58a7ba4643bea5d717 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 12 Dec 2018 20:54:08 +0100 Subject: [PATCH 2/2] fixup! builtin rebase: call `git am` directly In the scripted version, we call `move_to_original_branch`, which updates `HEAD` to point to the original branch again, after updating that branch to point at the current commit. This does not require any worktree update. In the built-in version, we tried to reuse the `reset_head()` function, which however does try to update the worktree. Of course, as there are no changes, no actual worktree updates are performed. However, with an insanely large repository, even just looking whether we need to write anything takes a noticeable time. So let's avoid that in the built-in version, too. Signed-off-by: Johannes Schindelin --- builtin/rebase.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index 693cff2e16..e327c30b6b 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -505,7 +505,8 @@ static int move_to_original_branch(struct rebase_options *opts) opts->head_name, oid_to_hex(&opts->onto->object.oid)); strbuf_addf(&head_reflog, "rebase finished: returning to %s", opts->head_name); - ret = reset_head(NULL, "checkout", opts->head_name, 0, + ret = reset_head(NULL, "checkout", opts->head_name, + RESET_HEAD_REFS_ONLY, orig_head_reflog.buf, head_reflog.buf); strbuf_release(&orig_head_reflog);