From patchwork Wed Nov 15 14:33:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456826 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F2652E653 for ; Wed, 15 Nov 2023 14:33:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Drxc/S95" Received: from mail-lj1-x22f.google.com (mail-lj1-x22f.google.com [IPv6:2a00:1450:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A620818A for ; Wed, 15 Nov 2023 06:33:47 -0800 (PST) Received: by mail-lj1-x22f.google.com with SMTP id 38308e7fff4ca-2c83ffcdbe3so49004711fa.1 for ; Wed, 15 Nov 2023 06:33:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058825; x=1700663625; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NXjSLyezDw+VbVROY77kA+o1krDhTHXoiLhpC+E5xkQ=; b=Drxc/S95NY80GuCSNmMUhRwHv1nY39nniDlm8drPoXemNIm/BcL7hiGb/J2SW34BDm 0151OwgaUEM/H2sbESx6nW4CgqWjXocWgxO5ehHOTrbgCZl8px651+VCVActbulp6gqH k2No8IcBk4wX0P/m5hCqzNVpmGQxxkaQ1FCmF2MAPwvbECFO/L6W7KFh7YyEEAm84dYf G6m9ZsYHa503pw6OzLgRNTtUTVPzL0rUjqRMIPXqOAHVS1kKRVlj2TAfes7iOWduX+DD XK/136gPIi7s7T2Zs5x+/DbX1MfosBkZlppChi8lUQAA87XR5XG7VTkLs7RI9fdRHzwW /o3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058825; x=1700663625; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NXjSLyezDw+VbVROY77kA+o1krDhTHXoiLhpC+E5xkQ=; b=Z4kNsXbXYREcyjHYxQKgSJfaJqtDYyxNzNn9e/nSHcfxSHSawGXVCoWKIRzrmePO5+ KV0YZ+zFs/MZdDe9slx+cdloNo0Hipx7zJYLAVZk1MDIDqodjsglzECxxuF84Hxjog3M Ut1XpJ4KBB78TE6i0cLiMUx1/WPU975DmpzfrwizoTqn1L0Aguh26I0X275+nNTNMhW3 +nJ9xaEQfBmT90BfiTSaVvgPB2RnXRfeSSxTqh1DpGdRtrcwGJsartL5tao+UHH+RT80 Ur/681GtClsuPIZc4KidXZcA+XFSDVxUHrCrVhzD0iMP4+83vf5NDu8J4POYXh5udPnz BT6g== X-Gm-Message-State: AOJu0YxgQR7TTEfDsufe183SbYLoFhh3+FDWt4yHUX4rsTZD3+U6bXGn dQVIYNRA3qXWatM+ZAJKtAzBZ/fK5fo= X-Google-Smtp-Source: AGHT+IGU4PdAHnQ9yyDOPFUuTWC1WJ0kDZk4B0JM7P+HzQU2w+NOB99WEvpmdlYPZCJf2vtxqtao/Q== X-Received: by 2002:a2e:8512:0:b0:2c6:ee98:de83 with SMTP id j18-20020a2e8512000000b002c6ee98de83mr3992804lji.46.1700058824715; Wed, 15 Nov 2023 06:33:44 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:44 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 01/14] t6429: remove switching aspects of fast-rebase Date: Wed, 15 Nov 2023 15:33:14 +0100 Message-ID: <20231115143327.2441397-2-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren At the time t6429 was written, merge-ort was still under development, did not have quite as many tests, and certainly was not widely deployed. Since t6429 was exercising some codepaths just a little differently, we thought having them also test the "merge_switch_to_result()" bits of merge-ort was useful even though they weren't intrinsic to the real point of these tests. However, the value provided by doing extra testing of the "merge_switch_to_result()" bits has decreased a bit over time, and it's actively making it harder to refactor `test-tool fast-rebase` into `git replay`, which we are going to do in following commits. Dispense with these bits. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- t/helper/test-fast-rebase.c | 9 +-------- t/t6429-merge-sequence-rename-caching.sh | 9 +++++++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c index cac20a72b3..2bfab66b1b 100644 --- a/t/helper/test-fast-rebase.c +++ b/t/helper/test-fast-rebase.c @@ -194,7 +194,7 @@ int cmd__fast_rebase(int argc, const char **argv) last_commit = create_commit(result.tree, commit, last_commit); } - merge_switch_to_result(&merge_opt, head_tree, &result, 1, !result.clean); + merge_finalize(&merge_opt, &result); if (result.clean < 0) exit(128); @@ -213,9 +213,6 @@ int cmd__fast_rebase(int argc, const char **argv) } if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) die(_("unable to update HEAD")); - - prime_cache_tree(the_repository, the_repository->index, - result.tree); } else { fprintf(stderr, "\nAborting: Hit a conflict.\n"); strbuf_addf(&reflog_msg, "rebase progress up to %s", @@ -228,10 +225,6 @@ int cmd__fast_rebase(int argc, const char **argv) die("Failed to update %s", argv[4]); } } - if (write_locked_index(&the_index, &lock, - COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die(_("unable to write %s"), get_index_file()); - ret = (result.clean == 0); cleanup: strbuf_release(&reflog_msg); diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index d02fa16614..75d3fd2dba 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -72,6 +72,7 @@ test_expect_success 'caching renames does not preclude finding new ones' ' git switch upstream && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream~1..topic git ls-files >tracked-files && @@ -200,6 +201,7 @@ test_expect_success 'rename same file identically, then reintroduce it' ' export GIT_TRACE2_PERF && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream~1..topic && git ls-files >tracked && @@ -277,6 +279,7 @@ test_expect_success 'rename same file identically, then add file to old dir' ' export GIT_TRACE2_PERF && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream~1..topic && git ls-files >tracked && @@ -356,8 +359,6 @@ test_expect_success 'cached dir rename does not prevent noticing later conflict' test_must_fail test-tool fast-rebase --onto HEAD upstream~1 topic >output && #git cherry-pick upstream..topic && - grep CONFLICT..rename/rename output && - grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls ) @@ -456,6 +457,7 @@ test_expect_success 'dir rename unneeded, then add new file to old dir' ' export GIT_TRACE2_PERF && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && @@ -522,6 +524,7 @@ test_expect_success 'dir rename unneeded, then rename existing file into old dir export GIT_TRACE2_PERF && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && @@ -624,6 +627,7 @@ test_expect_success 'caching renames only on upstream side, part 1' ' export GIT_TRACE2_PERF && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && @@ -682,6 +686,7 @@ test_expect_success 'caching renames only on upstream side, part 2' ' export GIT_TRACE2_PERF && test-tool fast-rebase --onto HEAD upstream~1 topic && + git reset --hard topic && #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && From patchwork Wed Nov 15 14:33:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456828 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 69A7D1EB34 for ; Wed, 15 Nov 2023 14:33:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gLN4Jrj4" Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C23C18B for ; Wed, 15 Nov 2023 06:33:50 -0800 (PST) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-408425c7c10so55271775e9.0 for ; Wed, 15 Nov 2023 06:33:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058827; x=1700663627; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FX28VuiAHyjr49ukA0LIztxLQEDq2DWCFixAQ99AYvY=; b=gLN4Jrj40TV+ZyleRM5si7NXkV06M19+oL6sz+sZlEpjHbxHxnvrqtGe2bJJnHrYRo ckyspVKN/j/B2ugqPUW35h4yWoHLsRRFq3Ak63BLXk8UGDOjF/8j+0/0QS/9hSi6Wzmj /O4M1fbUqgGwVNkKYDhlGjaEMs3lCoF1J4/yU5JTmL3G2/raQqFZr1x2eMNzJXJhUYdD 5p/HQ/oiPDqhf+gCbGAoQ1FgbFnLje2gT4TfP68ft16ruYZWXCWBICkEgfTHamaQX87v /AMKv2jTZ+1jJGiRE1ZhIdbBl/o9OwJWpw8MwcmLqvrvJXA25tBvA/HFzBvpwNzJeB9w k+EQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058827; x=1700663627; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FX28VuiAHyjr49ukA0LIztxLQEDq2DWCFixAQ99AYvY=; b=gPJimRdl1vX0rmX8WBR11SXfFNIAgixYJPN4Tm+yt3hf3ouUgA3ijlBFptg2qnQgIf 0bE2JrsbxRrdPOj5p2UGPSSP3ksebDstpCcaLgFR9Heefgqm0L2/PRB9xbpQn43iRykU 6ySgIrCJiyaER39fmEFB2cVeYKfQ0K+GAr8IeNn5IyiSbQaN0Q54uOJVlT+HhSRUSl+x /K17kaUeMFXYpkNiSt5sfRznWqz1cbv8kUTb1FnyCPJ8LBF8SjrtiAPDtPGWYo3pi4KJ BSErShB3Gkn7kVPu3DzNGsWHmjGHkI4BtM8p5UWqu0JJ6Tgx5Dn7/g93lQHdAERwWmv6 x7hw== X-Gm-Message-State: AOJu0YwxvVuLxdWPl4aQ621vZFFm1xUkjzVnMJ9KSyQyCqXrCWjtXsU/ rfNZ58OHp3nb0KeBud4D/7MnSbyOjwk= X-Google-Smtp-Source: AGHT+IFnUeSl4IIatRr0CSAKD4mAUscLg931YGrH2vhQA3aNAdYZTcOF7MIGrNu9/XJpcAe98xfN2A== X-Received: by 2002:a05:600c:4446:b0:40a:392c:5b79 with SMTP id v6-20020a05600c444600b0040a392c5b79mr10729603wmn.14.1700058827235; Wed, 15 Nov 2023 06:33:47 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:45 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 02/14] replay: introduce new builtin Date: Wed, 15 Nov 2023 15:33:15 +0100 Message-ID: <20231115143327.2441397-3-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren For now, this is just a rename from `t/helper/test-fast-rebase.c` into `builtin/replay.c` with minimal changes to make it build appropriately. Let's add a stub documentation and a stub test script though. Subsequent commits will flesh out the capabilities of the new command and make it a more standard regular builtin. Helped-by: Johannes Schindelin Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- .gitignore | 1 + Documentation/git-replay.txt | 39 ++++++++++++ Makefile | 2 +- builtin.h | 1 + .../test-fast-rebase.c => builtin/replay.c | 29 +++------ command-list.txt | 1 + git.c | 1 + t/helper/test-tool.c | 1 - t/helper/test-tool.h | 1 - t/t3650-replay-basics.sh | 60 +++++++++++++++++++ t/t6429-merge-sequence-rename-caching.sh | 27 +++------ 11 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 Documentation/git-replay.txt rename t/helper/test-fast-rebase.c => builtin/replay.c (87%) create mode 100755 t/t3650-replay-basics.sh diff --git a/.gitignore b/.gitignore index 5e56e471b3..612c0f6a0f 100644 --- a/.gitignore +++ b/.gitignore @@ -135,6 +135,7 @@ /git-remote-ext /git-repack /git-replace +/git-replay /git-request-pull /git-rerere /git-reset diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.txt new file mode 100644 index 0000000000..0349058b66 --- /dev/null +++ b/Documentation/git-replay.txt @@ -0,0 +1,39 @@ +git-replay(1) +============= + +NAME +---- +git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos too + + +SYNOPSIS +-------- +[verse] +'git replay' --onto # EXPERIMENTAL + +DESCRIPTION +----------- + +Takes a range of commits, specified by and , and +replays them onto a new location (see `--onto` option below). + +THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. + +OPTIONS +------- + +--onto :: + Starting point at which to create the new commits. May be any + valid commit, and not just an existing branch name. + +EXIT STATUS +----------- + +For a successful, non-conflicted replay, the exit status is 0. When +the replay has conflicts, the exit status is 1. If the replay is not +able to complete (or start) due to some kind of error, the exit status +is something other than 0 or 1. + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Makefile b/Makefile index 03adcb5a48..3834bc1544 100644 --- a/Makefile +++ b/Makefile @@ -799,7 +799,6 @@ TEST_BUILTINS_OBJS += test-dump-split-index.o TEST_BUILTINS_OBJS += test-dump-untracked-cache.o TEST_BUILTINS_OBJS += test-env-helper.o TEST_BUILTINS_OBJS += test-example-decorate.o -TEST_BUILTINS_OBJS += test-fast-rebase.o TEST_BUILTINS_OBJS += test-find-pack.o TEST_BUILTINS_OBJS += test-fsmonitor-client.o TEST_BUILTINS_OBJS += test-genrandom.o @@ -1290,6 +1289,7 @@ BUILTIN_OBJS += builtin/remote-fd.o BUILTIN_OBJS += builtin/remote.o BUILTIN_OBJS += builtin/repack.o BUILTIN_OBJS += builtin/replace.o +BUILTIN_OBJS += builtin/replay.o BUILTIN_OBJS += builtin/rerere.o BUILTIN_OBJS += builtin/reset.o BUILTIN_OBJS += builtin/rev-list.o diff --git a/builtin.h b/builtin.h index d560baa661..28280636da 100644 --- a/builtin.h +++ b/builtin.h @@ -211,6 +211,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix); int cmd_remote_ext(int argc, const char **argv, const char *prefix); int cmd_remote_fd(int argc, const char **argv, const char *prefix); int cmd_repack(int argc, const char **argv, const char *prefix); +int cmd_replay(int argc, const char **argv, const char *prefix); int cmd_rerere(int argc, const char **argv, const char *prefix); int cmd_reset(int argc, const char **argv, const char *prefix); int cmd_restore(int argc, const char **argv, const char *prefix); diff --git a/t/helper/test-fast-rebase.c b/builtin/replay.c similarity index 87% rename from t/helper/test-fast-rebase.c rename to builtin/replay.c index 2bfab66b1b..f2d8444417 100644 --- a/t/helper/test-fast-rebase.c +++ b/builtin/replay.c @@ -1,17 +1,11 @@ /* - * "git fast-rebase" builtin command - * - * FAST: Forking Any Subprocesses (is) Taboo - * - * This is meant SOLELY as a demo of what is possible. sequencer.c and - * rebase.c should be refactored to use the ideas here, rather than attempting - * to extend this file to replace those (unless Phillip or Dscho say that - * refactoring is too hard and we need a clean slate, but I'm guessing that - * refactoring is the better route). + * "git replay" builtin command */ #define USE_THE_INDEX_VARIABLE -#include "test-tool.h" +#include "git-compat-util.h" + +#include "builtin.h" #include "cache-tree.h" #include "commit.h" #include "environment.h" @@ -27,7 +21,8 @@ #include "sequencer.h" #include "setup.h" #include "strvec.h" -#include "tree.h" +#include +#include static const char *short_commit_name(struct commit *commit) { @@ -94,7 +89,7 @@ static struct commit *create_commit(struct tree *tree, return (struct commit *)obj; } -int cmd__fast_rebase(int argc, const char **argv) +int cmd_replay(int argc, const char **argv, const char *prefix) { struct commit *onto; struct commit *last_commit = NULL, *last_picked_commit = NULL; @@ -110,14 +105,8 @@ int cmd__fast_rebase(int argc, const char **argv) struct strbuf branch_name = STRBUF_INIT; int ret = 0; - /* - * test-tool stuff doesn't set up the git directory by default; need to - * do that manually. - */ - setup_git_directory(); - if (argc == 2 && !strcmp(argv[1], "-h")) { - printf("Sorry, I am not a psychiatrist; I can not give you the help you need. Oh, you meant usage...\n"); + printf("git replay --onto # EXPERIMENTAL\n"); exit(129); } @@ -136,7 +125,7 @@ int cmd__fast_rebase(int argc, const char **argv) if (repo_read_index(the_repository) < 0) BUG("Could not read index"); - repo_init_revisions(the_repository, &revs, NULL); + repo_init_revisions(the_repository, &revs, prefix); revs.verbose_header = 1; revs.max_parents = 1; revs.cherry_mark = 1; diff --git a/command-list.txt b/command-list.txt index 54b2a50f5f..c4cd0f352b 100644 --- a/command-list.txt +++ b/command-list.txt @@ -160,6 +160,7 @@ git-reflog ancillarymanipulators complete git-remote ancillarymanipulators complete git-repack ancillarymanipulators complete git-replace ancillarymanipulators complete +git-replay plumbingmanipulators git-request-pull foreignscminterface complete git-rerere ancillaryinterrogators git-reset mainporcelain history diff --git a/git.c b/git.c index c67e44dd82..7068a184b0 100644 --- a/git.c +++ b/git.c @@ -594,6 +594,7 @@ static struct cmd_struct commands[] = { { "remote-fd", cmd_remote_fd, NO_PARSEOPT }, { "repack", cmd_repack, RUN_SETUP }, { "replace", cmd_replace, RUN_SETUP }, + { "replay", cmd_replay, RUN_SETUP }, { "rerere", cmd_rerere, RUN_SETUP }, { "reset", cmd_reset, RUN_SETUP }, { "restore", cmd_restore, RUN_SETUP | NEED_WORK_TREE }, diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 876cd2dc31..37ba996539 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -30,7 +30,6 @@ static struct test_cmd cmds[] = { { "dump-untracked-cache", cmd__dump_untracked_cache }, { "env-helper", cmd__env_helper }, { "example-decorate", cmd__example_decorate }, - { "fast-rebase", cmd__fast_rebase }, { "find-pack", cmd__find_pack }, { "fsmonitor-client", cmd__fsmonitor_client }, { "genrandom", cmd__genrandom }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 70dd4eba11..8a1a7c63da 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -24,7 +24,6 @@ int cmd__dump_untracked_cache(int argc, const char **argv); int cmd__dump_reftable(int argc, const char **argv); int cmd__env_helper(int argc, const char **argv); int cmd__example_decorate(int argc, const char **argv); -int cmd__fast_rebase(int argc, const char **argv); int cmd__find_pack(int argc, const char **argv); int cmd__fsmonitor_client(int argc, const char **argv); int cmd__genrandom(int argc, const char **argv); diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh new file mode 100755 index 0000000000..36c1b5082a --- /dev/null +++ b/t/t3650-replay-basics.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='basic git replay tests' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +GIT_AUTHOR_NAME=author@name +GIT_AUTHOR_EMAIL=bogus@email@address +export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL + +test_expect_success 'setup' ' + test_commit A && + test_commit B && + + git switch -c topic1 && + test_commit C && + git switch -c topic2 && + test_commit D && + test_commit E && + git switch topic1 && + test_commit F && + git switch -c topic3 && + test_commit G && + test_commit H && + git switch -c topic4 main && + test_commit I && + test_commit J && + + git switch -c next main && + test_commit K && + git merge -m "Merge topic1" topic1 && + git merge -m "Merge topic2" topic2 && + git merge -m "Merge topic3" topic3 && + >evil && + git add evil && + git commit --amend && + git merge -m "Merge topic4" topic4 && + + git switch main && + test_commit L && + test_commit M && + + git switch -c conflict B && + test_commit C.conflict C.t conflict +' + +test_expect_success 'using replay to rebase two branches, one on top of other' ' + git switch main && + + git replay --onto main topic1 topic2 >result && + + git log --format=%s $(cut -f 3 -d " " result) >actual && + test_write_lines E D M L B A >expect && + test_cmp expect actual +' + +test_done diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index 75d3fd2dba..7670b72008 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -71,9 +71,8 @@ test_expect_success 'caching renames does not preclude finding new ones' ' git switch upstream && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream~1..topic git ls-files >tracked-files && test_line_count = 2 tracked-files && @@ -141,8 +140,7 @@ test_expect_success 'cherry-pick both a commit and its immediate revert' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream~1..topic && + git replay --onto HEAD upstream~1 topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 1 calls @@ -200,9 +198,8 @@ test_expect_success 'rename same file identically, then reintroduce it' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream~1..topic && git ls-files >tracked && test_line_count = 2 tracked && @@ -278,9 +275,8 @@ test_expect_success 'rename same file identically, then add file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream~1..topic && git ls-files >tracked && test_line_count = 4 tracked && @@ -356,8 +352,7 @@ test_expect_success 'cached dir rename does not prevent noticing later conflict' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test_must_fail test-tool fast-rebase --onto HEAD upstream~1 topic >output && - #git cherry-pick upstream..topic && + test_must_fail git replay --onto HEAD upstream~1 topic >output && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls @@ -456,9 +451,8 @@ test_expect_success 'dir rename unneeded, then add new file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls && @@ -523,9 +517,8 @@ test_expect_success 'dir rename unneeded, then rename existing file into old dir GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 3 calls && @@ -626,9 +619,8 @@ test_expect_success 'caching renames only on upstream side, part 1' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 1 calls && @@ -685,9 +677,8 @@ test_expect_success 'caching renames only on upstream side, part 2' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic && git reset --hard topic && - #git cherry-pick upstream..topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls && From patchwork Wed Nov 15 14:33:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456829 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C80017983 for ; Wed, 15 Nov 2023 14:33:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QexKe8eV" Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0046818D for ; Wed, 15 Nov 2023 06:33:50 -0800 (PST) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4084b0223ccso53567015e9.2 for ; Wed, 15 Nov 2023 06:33:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058828; x=1700663628; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gucjjutSMVzlO70K3OzRYYC9EXAij3BX9+NVIUVS8yc=; b=QexKe8eVIg4wHAfG2W6zH8kT3NtlOjf8zEh4guHUMhk+wIuSfOx3c5yHXzUqqLQA8M wcsaw2MDuweHFNegK+FyqleLRizEJD3raCEfW72iLQWB0PL5o43GnRdJVR7Qa9+MEy0M XeFKn6kfDuDhtS0KYvMFACQnEy/pFDMdsvaTbC/UOilphceWTgzG7zTc1gnjhsNqLxev 4bEgrw6IjhEUw6joWpJYBoEsH26uh9FqGrBOieFkCCaRCu798f73y6o8GZNZf4mVnThm up1PI/RYD7asnLZfLqEyRQ/LC8pKNNI8KpIignvNRRsrNL8Rz5wTlt7e9dZQJSumjjqY smCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058828; x=1700663628; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gucjjutSMVzlO70K3OzRYYC9EXAij3BX9+NVIUVS8yc=; b=WD0SsFo/84v1+wpsWVkAF7GkRM3hRrhD69VVw+EsBgYZvhPdQvXj8o+HpHrDacREsT xpC/P0R/uLev0H5O1YGrI2UvVlyu1+gQ1oJP/pUMuY2YrRHgAJF3EHrj9dlOtuv+khxf QSL0rpfyz+iotsoZmfvEn1c1oIGzck2GhKju/+/bspV5gZXOU0dQCgL1CVp++9nGEbH/ DefJ+l+gsTiEZIuedBBDIjbQVFa0OnuS95PVmzEa0YyXdWRt5Mq+AFgs6624+nIcmXSw 0PdgJOoWMIAb5jsmPJ0fuAdgjn4xYmfQwt6bdUrtVpg00tuin39cauoQxfAndBmuWlze puZQ== X-Gm-Message-State: AOJu0YyoyBFPfp6TmmhjcD1GT3DOhkGPKRVzsX6svgem4fEk9ide/GZI rdP9ZJq8iIf7KQsNO6Sd8wXJnbGaHyo= X-Google-Smtp-Source: AGHT+IFgBkglXuD1rE18SrX51JHc0IC//2o1AZxufRN5ip05Pq75qCngMbMWP3/fRy9ImNqZDaWBDA== X-Received: by 2002:a05:600c:35d2:b0:408:55f8:7de with SMTP id r18-20020a05600c35d200b0040855f807demr9115662wmq.28.1700058828053; Wed, 15 Nov 2023 06:33:48 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:47 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 03/14] replay: start using parse_options API Date: Wed, 15 Nov 2023 15:33:16 +0100 Message-ID: <20231115143327.2441397-4-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren Instead of manually parsing arguments, let's start using the parse_options API. This way this new builtin will look more standard, and in some upcoming commits will more easily be able to handle more command line options. Note that we plan to later use standard revision ranges instead of hardcoded " " arguments. When we will use standard revision ranges, it will be easier to check if there are no spurious arguments if we keep ARGV[0], so let's call parse_options() with PARSE_OPT_KEEP_ARGV0 even if we don't need ARGV[0] right now to avoid some useless code churn. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index f2d8444417..afabb844d3 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -15,7 +15,7 @@ #include "lockfile.h" #include "merge-ort.h" #include "object-name.h" -#include "read-cache-ll.h" +#include "parse-options.h" #include "refs.h" #include "revision.h" #include "sequencer.h" @@ -92,6 +92,7 @@ static struct commit *create_commit(struct tree *tree, int cmd_replay(int argc, const char **argv, const char *prefix) { struct commit *onto; + const char *onto_name = NULL; struct commit *last_commit = NULL, *last_picked_commit = NULL; struct object_id head; struct lock_file lock = LOCK_INIT; @@ -105,16 +106,32 @@ int cmd_replay(int argc, const char **argv, const char *prefix) struct strbuf branch_name = STRBUF_INIT; int ret = 0; - if (argc == 2 && !strcmp(argv[1], "-h")) { - printf("git replay --onto # EXPERIMENTAL\n"); - exit(129); + const char * const replay_usage[] = { + N_("git replay --onto # EXPERIMENTAL"), + NULL + }; + struct option replay_options[] = { + OPT_STRING(0, "onto", &onto_name, + N_("revision"), + N_("replay onto given commit")), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, replay_options, replay_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT); + + if (!onto_name) { + error(_("option --onto is mandatory")); + usage_with_options(replay_usage, replay_options); } - if (argc != 5 || strcmp(argv[1], "--onto")) - die("usage: read the code, figure out how to use it, then do so"); + if (argc != 3) { + error(_("bad number of arguments")); + usage_with_options(replay_usage, replay_options); + } - onto = peel_committish(argv[2]); - strbuf_addf(&branch_name, "refs/heads/%s", argv[4]); + onto = peel_committish(onto_name); + strbuf_addf(&branch_name, "refs/heads/%s", argv[2]); /* Sanity check */ if (repo_get_oid(the_repository, "HEAD", &head)) @@ -126,6 +143,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) BUG("Could not read index"); repo_init_revisions(the_repository, &revs, prefix); + revs.verbose_header = 1; revs.max_parents = 1; revs.cherry_mark = 1; @@ -134,7 +152,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix) revs.right_only = 1; revs.sort_order = REV_SORT_IN_GRAPH_ORDER; revs.topo_order = 1; - strvec_pushl(&rev_walk_args, "", argv[4], "--not", argv[3], NULL); + + strvec_pushl(&rev_walk_args, "", argv[2], "--not", argv[1], NULL); if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) { ret = error(_("unhandled options")); @@ -197,8 +216,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix) &last_commit->object.oid, &last_picked_commit->object.oid, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[4]); - die("Failed to update %s", argv[4]); + error(_("could not update %s"), argv[2]); + die("Failed to update %s", argv[2]); } if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) die(_("unable to update HEAD")); @@ -210,8 +229,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix) &last_commit->object.oid, &head, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[4]); - die("Failed to update %s", argv[4]); + error(_("could not update %s"), argv[2]); + die("Failed to update %s", argv[2]); } } ret = (result.clean == 0); From patchwork Wed Nov 15 14:33:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456830 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 42A112E658 for ; Wed, 15 Nov 2023 14:33:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Yxlrfw7H" Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [IPv6:2a00:1450:4864:20::22a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 197EE189 for ; Wed, 15 Nov 2023 06:33:53 -0800 (PST) Received: by mail-lj1-x22a.google.com with SMTP id 38308e7fff4ca-2c50906f941so98288581fa.2 for ; Wed, 15 Nov 2023 06:33:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058830; x=1700663630; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=E691cqJfsqH+4jSY4gnfdIU7rI78N7x762/MRRyf3VI=; b=Yxlrfw7HMS4ShAP0ENIN+GsVuJOP/y7M8qDZzAHeq4+Helsrk8eCi5TJYM5SqAQiKl r62TESIdp1q5At/JKFerAg+8QsP4oDwZwdtKRu2Zj71Qv/9oxyc48CViYcWI3VLTm4UR ObqYtKAMmhQrrrapKEa7tyU4M6q4ZtQGVTIh00nagcNisymJ77KYqLiIRm0hj4STjVSP VYMBTL+IlNWY9DheG5hDivXVpUf574YVPgVWqNUAMqnDMV/SciGtMTk4QUwd9E/kqdAv VcPqMapg+10+ajWSxGvV9xDoKuA1aOv4Gt/22yxAe6O2+F7MkPEOs130doV+60oKauE+ h7fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058830; x=1700663630; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=E691cqJfsqH+4jSY4gnfdIU7rI78N7x762/MRRyf3VI=; b=D+HOpXYrUtVbm39v/2qs5Xz4LPIQW+RG8Wsn6NlyprhYIdMlSEIKZJriCuPKHJSQT1 et6VuoFSSatNb2ekgUdVy6T14/UbyGDvkGX5f+UDCjF5n2qyg/5XVPqn/3IKtL+sjUB3 CT0sQ3QbtAwe6ca8M3JeEusuwSPoPWefVviaYDpJcyVLSIjRwYjvtv52uxVzTSuRW/+u ZJHNpLKjlBQ5A2zwrWsAx2mcQRA+1/XMP7gCK9sPt3lkbO/4Xux2U5htnw1MvOeiQ/m1 VoGn1fFHVu1yuvXdthqRGnuT50WPLvFBYGYA/91iSul8e7U8mXcZaBLpHJEG3T0pSobR 1L6Q== X-Gm-Message-State: AOJu0Yx83tBVFbFsJI28caohTXroGTN5UH3Bj07CJbljeo3d9Pch4j3U NVhbvhxiwnkiIxioxzEeIRtQxa3Ymk4= X-Google-Smtp-Source: AGHT+IHFk2ngDEoaUYi650Fud9eHQe2PyAOA8cNJlw6qkwoAk+wwd28+ugyYmLxSWk+DFTbnPr3UQg== X-Received: by 2002:a2e:7811:0:b0:2c5:1e70:7d30 with SMTP id t17-20020a2e7811000000b002c51e707d30mr4488690ljc.30.1700058830434; Wed, 15 Nov 2023 06:33:50 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:48 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 04/14] replay: die() instead of failing assert() Date: Wed, 15 Nov 2023 15:33:17 +0100 Message-ID: <20231115143327.2441397-5-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren It's not a good idea for regular Git commands to use an assert() to check for things that could happen but are not supported. Let's die() with an explanation of the issue instead. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/builtin/replay.c b/builtin/replay.c index afabb844d3..32dbaaf028 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -179,7 +179,12 @@ int cmd_replay(int argc, const char **argv, const char *prefix) fprintf(stderr, "Rebasing %s...\r", oid_to_hex(&commit->object.oid)); - assert(commit->parents && !commit->parents->next); + + if (!commit->parents) + die(_("replaying down to root commit is not supported yet!")); + if (commit->parents->next) + die(_("replaying merge commits is not supported yet!")); + base = commit->parents->item; next_tree = repo_get_commit_tree(the_repository, commit); From patchwork Wed Nov 15 14:33:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456831 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 267AA2EAE1 for ; Wed, 15 Nov 2023 14:33:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cqqEyDpS" Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B408C18E for ; Wed, 15 Nov 2023 06:33:54 -0800 (PST) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-40836ea8cbaso51181375e9.0 for ; Wed, 15 Nov 2023 06:33:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058832; x=1700663632; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=RkCo+BViWWdWCywWrH14NiTrFEqnHkxrdCRhzBg115M=; b=cqqEyDpShequ8Im/RvTPQOp9hwe5bAANODzFpV11ZDfOKrCsFVZVImVGuDBROpGwyH uHNyf53/an7JoPI1K0RZRFXt0noiA9a1eYABX3plj6/8/OEUyd5BISZwAeuaqhCZQjoH UaN5GHz3VewQ1ajenC/tPsO7XJIUV/WpCmiLRFPnE8LjQyJ6s8QqHsegTXqW3g+eAkdI TUtRIWMrfq6kGWiGqi6fDnNl63DOLpRorYgK0cLS+WbSddhtg9TjsHAD0/oYUY2CDG/3 qvVfeZ/slkpsdoRFLPxFyRI3Q6Pfhsuno5qqi5nYAkW6TwrUX+xD5P6Rw3mnUbHdVZE1 DmUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058832; x=1700663632; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RkCo+BViWWdWCywWrH14NiTrFEqnHkxrdCRhzBg115M=; b=XCc/8J31p1SzNtJ6uuzbKFfE3AXuoPkhEsvfHpIQZ1pQd955MUg1RbJ7Dc2WpcZr4S AyOJ5QmsMSylkVXd5mebj77p3Mh6z44dVM0WILz4LlRX+NySyf+GmbXIffZZihSLv1Jv 98+DH0+kUb8DPx/3I/VEW+Mg4vyf1xOeEB5aEDZ3s+fmslLIkBk+rd4MInkNnWqR/VFm 9uByVHwzFtlHbyD6zjltVw9tnjPjnSGjQ+v0PfjYkLvw3XBfW1/dpcFSReh+qZlfAjle cPFssaVJLhcevd0DtlpNYdoNlh6iJkdBo4sVYOYB6P0rbFBqcyFR2dWoUBr73nBUsbSV iSIg== X-Gm-Message-State: AOJu0YwcUKjXnOTZdryudpm6sRTdrIn+nUbzJk97XAnzquyLiflUeV8O C/9RHwkkWTc0NtC701/UdiaHB7AJJJo= X-Google-Smtp-Source: AGHT+IG5yEv61pJBdhAAwD7nq74RnwSpnaFXqCkhYRMa+EUX91uEdrjfrW4jgJbabTnyjVWrLNLfxg== X-Received: by 2002:a05:600c:1914:b0:405:3885:490a with SMTP id j20-20020a05600c191400b004053885490amr11056122wmq.0.1700058832177; Wed, 15 Nov 2023 06:33:52 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:50 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 05/14] replay: introduce pick_regular_commit() Date: Wed, 15 Nov 2023 15:33:18 +0100 Message-ID: <20231115143327.2441397-6-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren Let's refactor the code to handle a regular commit (a commit that is neither a root commit nor a merge commit) into a single function instead of keeping it inside cmd_replay(). This is good for separation of concerns, and this will help further work in the future to replay merge commits. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 54 ++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index 32dbaaf028..5c4cbd11db 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -89,6 +89,35 @@ static struct commit *create_commit(struct tree *tree, return (struct commit *)obj; } +static struct commit *pick_regular_commit(struct commit *pickme, + struct commit *last_commit, + struct merge_options *merge_opt, + struct merge_result *result) +{ + struct commit *base; + struct tree *pickme_tree, *base_tree; + + base = pickme->parents->item; + + pickme_tree = repo_get_commit_tree(the_repository, pickme); + base_tree = repo_get_commit_tree(the_repository, base); + + merge_opt->branch2 = short_commit_name(pickme); + merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2); + + merge_incore_nonrecursive(merge_opt, + base_tree, + result->tree, + pickme_tree, + result); + + free((char*)merge_opt->ancestor); + merge_opt->ancestor = NULL; + if (!result->clean) + return NULL; + return create_commit(result->tree, pickme, last_commit); +} + int cmd_replay(int argc, const char **argv, const char *prefix) { struct commit *onto; @@ -100,7 +129,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) struct rev_info revs; struct commit *commit; struct merge_options merge_opt; - struct tree *next_tree, *base_tree, *head_tree; + struct tree *head_tree; struct merge_result result; struct strbuf reflog_msg = STRBUF_INIT; struct strbuf branch_name = STRBUF_INIT; @@ -175,7 +204,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) result.tree = head_tree; last_commit = onto; while ((commit = get_revision(&revs))) { - struct commit *base; + struct commit *pick; fprintf(stderr, "Rebasing %s...\r", oid_to_hex(&commit->object.oid)); @@ -185,26 +214,11 @@ int cmd_replay(int argc, const char **argv, const char *prefix) if (commit->parents->next) die(_("replaying merge commits is not supported yet!")); - base = commit->parents->item; - - next_tree = repo_get_commit_tree(the_repository, commit); - base_tree = repo_get_commit_tree(the_repository, base); - - merge_opt.branch2 = short_commit_name(commit); - merge_opt.ancestor = xstrfmt("parent of %s", merge_opt.branch2); - - merge_incore_nonrecursive(&merge_opt, - base_tree, - result.tree, - next_tree, - &result); - - free((char*)merge_opt.ancestor); - merge_opt.ancestor = NULL; - if (!result.clean) + pick = pick_regular_commit(commit, last_commit, &merge_opt, &result); + if (!pick) break; + last_commit = pick; last_picked_commit = commit; - last_commit = create_commit(result.tree, commit, last_commit); } merge_finalize(&merge_opt, &result); From patchwork Wed Nov 15 14:33:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456832 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4AF72DF67 for ; Wed, 15 Nov 2023 14:33:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EAYe6ZJi" Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FB73189 for ; Wed, 15 Nov 2023 06:33:56 -0800 (PST) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-4083f61322fso53646315e9.1 for ; Wed, 15 Nov 2023 06:33:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058834; x=1700663634; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ze0ZZh/TMWbCDcHijjRV14IrjUZbWlQ3RkhaWbRVZXI=; b=EAYe6ZJi85IMVCbf5hq7kfWRAw2UDfjcoqjObmPxBHI2fVIAhx90s835aPH+YALCh2 qRAWJNyFpJtGSr0Ep6/pBOdZGfxYXAJHQcNrf5uJ3czKVIZDnDgz0mCdAo02qz1MHpt4 uTkkil/UmQQ9vkF3CqeaSe+PhfxEWqwZ995u3gSx9CnDwhg7lkLz5FQYPH8ikPogqpyE qNGfVpJFtAa81WG0fY1vW1BTkRmTjJPf+4Uo5K0GKGWgFo81Mc5RWa1FQZnH7HuL8E30 s57rzVV0Q4YseqQ+jmh53sDA3u7p5aolqH89z3YFDTz9mWQFS3liN3M25nb1e4DKSKT9 qpwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058834; x=1700663634; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ze0ZZh/TMWbCDcHijjRV14IrjUZbWlQ3RkhaWbRVZXI=; b=HO8v7wvoflg3qTdKVKWbWujokJ58BIonC3OL6lmtqx3WiYC9X9m7F609y2s4jhpsua QBxEUuPUTXybVxipVrDtJCiald4QyB/Hv7uVYvFYDrMI1GZERxcXk+7PXJ0bzHI+q0Ue nhpX+h4H4GO8UXFYFSDO7DjaEQ9LmRDoSCINgMQJ/k2RrQQuU0bfSlMflT352WCT2QCL i2/cAm5S9QRxvAK5Q1OtzEFHJU0n84V5gXA72OXyw9+84i5frsmK9hpWmGv4EDhchuO9 u5lEkxWk/fPCiWyvDoxs6pEKfrOrmxpIiwUsicKABzgmy3IwMhaUzG+OWybFvhG9lN0W gs/g== X-Gm-Message-State: AOJu0YylZHpl0BYpXQ2tuDlemNVvCvF8ArWm63Zf3W8whTZhvLUJyB3m in2Ge7yHsQ4Fa5IH7N1Wa+PglYW8Ypw= X-Google-Smtp-Source: AGHT+IG4zEuvIBgL9D7K/rCTwrBTdRleXGUdB2VScBuhFVzqYH7CFR5+UIWXR0U7UY7qcK9QUwbyew== X-Received: by 2002:a05:600c:34ce:b0:409:773:cf62 with SMTP id d14-20020a05600c34ce00b004090773cf62mr10494296wmq.39.1700058834206; Wed, 15 Nov 2023 06:33:54 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:52 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 06/14] replay: change rev walking options Date: Wed, 15 Nov 2023 15:33:19 +0100 Message-ID: <20231115143327.2441397-7-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren Let's force the rev walking options we need after calling setup_revisions() instead of before. This might override some user supplied rev walking command line options though. So let's detect that and warn users by: a) setting the desired values, before setup_revisions(), b) checking after setup_revisions() whether these values differ from the desired values, c) if so throwing a warning and setting the desired values again. We want the command to work from older commits to newer ones by default. Also we don't want history simplification, as we want to deal with all the commits in the affected range. Helped-by: Johannes Schindelin Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index 5c4cbd11db..8302d35eca 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -173,22 +173,56 @@ int cmd_replay(int argc, const char **argv, const char *prefix) repo_init_revisions(the_repository, &revs, prefix); - revs.verbose_header = 1; - revs.max_parents = 1; - revs.cherry_mark = 1; - revs.limited = 1; + strvec_pushl(&rev_walk_args, "", argv[2], "--not", argv[1], NULL); + + /* + * Set desired values for rev walking options here. If they + * are changed by some user specified option in setup_revisions() + * below, we will detect that below and then warn. + * + * TODO: In the future we might want to either die(), or allow + * some options changing these values if we think they could + * be useful. + */ revs.reverse = 1; - revs.right_only = 1; revs.sort_order = REV_SORT_IN_GRAPH_ORDER; revs.topo_order = 1; - - strvec_pushl(&rev_walk_args, "", argv[2], "--not", argv[1], NULL); + revs.simplify_history = 0; if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) { ret = error(_("unhandled options")); goto cleanup; } + /* + * Detect and warn if we override some user specified rev + * walking options. + */ + if (revs.reverse != 1) { + warning(_("some rev walking options will be overridden as " + "'%s' bit in 'struct rev_info' will be forced"), + "reverse"); + revs.reverse = 1; + } + if (revs.sort_order != REV_SORT_IN_GRAPH_ORDER) { + warning(_("some rev walking options will be overridden as " + "'%s' bit in 'struct rev_info' will be forced"), + "sort_order"); + revs.sort_order = REV_SORT_IN_GRAPH_ORDER; + } + if (revs.topo_order != 1) { + warning(_("some rev walking options will be overridden as " + "'%s' bit in 'struct rev_info' will be forced"), + "topo_order"); + revs.topo_order = 1; + } + if (revs.simplify_history != 0) { + warning(_("some rev walking options will be overridden as " + "'%s' bit in 'struct rev_info' will be forced"), + "simplify_history"); + revs.simplify_history = 0; + } + strvec_clear(&rev_walk_args); if (prepare_revision_walk(&revs) < 0) { From patchwork Wed Nov 15 14:33:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456833 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7C612FC5E for ; Wed, 15 Nov 2023 14:33:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HWcIOmsi" Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B955187 for ; Wed, 15 Nov 2023 06:33:58 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-4079ed65582so53328585e9.1 for ; Wed, 15 Nov 2023 06:33:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058836; x=1700663636; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qlX1vPNSw+hqdLdu0xZ2UW5XuEXNe6kchLDblMoMQbo=; b=HWcIOmsijaI8cPKkq3HC1kIidK4zg9Ela6V8Dsv97/nJq06Y0SoG1n9zbZB4B2NszM q57FS4KmpiS3/MjeLOOt+JGBsSGerJVhxFsZN0D/V5U8mUd/hgZ1kqqfyJZ9dB7aF7tz QFTMgNPtlCfI4QB9iXDi7TnnRUBRLCwS73C4nsKDB9jDDf78XgHNIZkyfzQkA9F/jWs5 SKe/oci1xLlxXELhJtJvZTzLJvFVz22QlnJSuPTKIPDNqEtnx/CIX2j+mkTOCbBdteHt RBc8NT8d2HtGWPr0pD56+h4xVKI0jx/Trv89tTiaD+jiFilsM+vfipznmC43k5o/7grD rQ9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058836; x=1700663636; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qlX1vPNSw+hqdLdu0xZ2UW5XuEXNe6kchLDblMoMQbo=; b=FvayyGPCncMeoE5e3RL2ZXQTE0iFDGNeX4B6rTx946rzCvbxaxMF2epc7GKYHIqcGb 46ZKmIjEkhjh2XDlZkvBo8ivoxE8eIt1ImjbGea9+iEpWRLg+wlM5DxZN8p+d5iCxwUD dzE42r9tpQOqQMHAIqiSYNdPMSpThZsuYdsAeneh20VRQkk5zs3OfgCT3NnNOpso9FyV C+8o4bOlLJoY+vjXoj4SxIH+43tF0X88zxTfCADWwZVB1JnPMXsojGJiuc6M1PRMzA0q mLz2n9HHUnuwWawzvXhhwCsxh2dQWr5q9s39Yhk4aXGJ0RVd8B7cgeqlYYi14OVn0jN6 RC/A== X-Gm-Message-State: AOJu0YxK13ufDAeO12bByNvPofumXJr7r5ysxx0ysjh704mGRKm+K58R dSeR02ORbyujMaNqQA2AmsphQI1TwhI= X-Google-Smtp-Source: AGHT+IENChSEZFc89sn+HyZxk8pYPT+SOeY10fxq2UMDwSzlj4qOsZHYMjjiYw+mujyG4E3s7SHOfA== X-Received: by 2002:a05:600c:310e:b0:408:80bb:ae8d with SMTP id g14-20020a05600c310e00b0040880bbae8dmr10636916wmo.32.1700058835732; Wed, 15 Nov 2023 06:33:55 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:54 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 07/14] replay: add an important FIXME comment about gpg signing Date: Wed, 15 Nov 2023 15:33:20 +0100 Message-ID: <20231115143327.2441397-8-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren We want to be able to handle signed commits in some way in the future, but we are not ready to do it now. So for the time being let's just add a FIXME comment to remind us about it. These are different ways we could handle them: - in case of a cli user and if there was an interactive mode, we could perhaps ask if the user wants to sign again - we could add an option to just fail if there are signed commits Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/replay.c b/builtin/replay.c index 8302d35eca..2e1df83027 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -62,7 +62,7 @@ static struct commit *create_commit(struct tree *tree, struct object *obj; struct commit_list *parents = NULL; char *author; - char *sign_commit = NULL; + char *sign_commit = NULL; /* FIXME: cli users might want to sign again */ struct commit_extra_header *extra; struct strbuf msg = STRBUF_INIT; const char *out_enc = get_commit_output_encoding(); From patchwork Wed Nov 15 14:33:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456834 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 85B4E3307E for ; Wed, 15 Nov 2023 14:34:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NM4Ieqtb" Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 531C3189 for ; Wed, 15 Nov 2023 06:34:00 -0800 (PST) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-407da05f05aso51004225e9.3 for ; Wed, 15 Nov 2023 06:34:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058837; x=1700663637; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=j0Lp+OwVfnW3WJA+jS6ViZyTYfL9erxx17/e1CCIZb0=; b=NM4IeqtbNAVXedgNO7vQ/r9ZRTxn+ss216D0OMdLnaWrf6rXpNpMNsp85jv3Rvf5je KtisgQLTlYW0A8/QG4ubw6YhqU3j1hkXE1qzu9ha7mcWyxr1bgi7UjtSNJyUVt+evDOQ LN3w7KfYQLic31Kq8ZQrZZbl6J+jOXZSokm7WMfTvFBj2YiN3pFj+5xeKrIbr98Of4mj S2Gk3UIdSyeRbDDC+qpdspxfy6/a3h6Uq9lD1OrdlqQFWgvC/1uTFPLdqY6Op5leWYb0 KNcbTDgzVS1+3OABFfVCIZsseH9KefFZtaFm3qrJSF+eRNrc6vVyaGHiWWDivB0ZgK+v BivA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058837; x=1700663637; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=j0Lp+OwVfnW3WJA+jS6ViZyTYfL9erxx17/e1CCIZb0=; b=d6YOvMHDJV57pZmkX/P5yOA5uFPvcZJnqEvBT51/2ZDHHrne3Ig6hRlIa2xZalpacK XP1rQghH8nSdoab1U+UkzerZwMoy/1onMAfB0jAwfDOdC0bhAME3TgP9kggjVur+o3NV Oat3DBmlFjVtmHJyMW4RUH5LCclS2fvwzs5f+ZrHvkr8soiqcOPy4ifJ/5fascFP7SJz b2YRTuPQTIWYZAdoyF+SfmstUrxTojcELX+w56R0nC52eIskm8xE6kcJHwFWL8pm0704 mjfg11eFBLwl4HjWBKY3dUgkOgqUQk0A/H4dAU+oYE2rA8HA6K0x15Nq1eM+uw+qKsZc jaLg== X-Gm-Message-State: AOJu0YzxYZ1QyhxR3WhdC4CnnkiiX8M8Hi3atQOsnju31xIF9lYlTzlK xZ9RsEbR+fzz97f/iVZ3daR+4wyKREg= X-Google-Smtp-Source: AGHT+IF1OGIZ0b7RF1wnVGD3PAeKPft4zdfqlBoQzuLK6d0POdQN+1hyoj72+pNU5ueEiHT0vPHQHg== X-Received: by 2002:a05:600c:2217:b0:408:3975:e225 with SMTP id z23-20020a05600c221700b004083975e225mr10749289wml.40.1700058837412; Wed, 15 Nov 2023 06:33:57 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:56 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 08/14] replay: remove progress and info output Date: Wed, 15 Nov 2023 15:33:21 +0100 Message-ID: <20231115143327.2441397-9-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren The replay command will be changed in a follow up commit, so that it will not update refs directly, but instead it will print on stdout a list of commands that can be consumed by `git update-ref --stdin`. We don't want this output to be polluted by its current low value output, so let's just remove the latter. In the future, when the command gets an option to update refs by itself, it will make a lot of sense to display a progress meter, but we are not there yet. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index 2e1df83027..1035435705 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -232,7 +232,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) init_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); - merge_opt.show_rename_progress = 1; + merge_opt.show_rename_progress = 0; merge_opt.branch1 = "HEAD"; head_tree = repo_get_commit_tree(the_repository, onto); result.tree = head_tree; @@ -240,9 +240,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) while ((commit = get_revision(&revs))) { struct commit *pick; - fprintf(stderr, "Rebasing %s...\r", - oid_to_hex(&commit->object.oid)); - if (!commit->parents) die(_("replaying down to root commit is not supported yet!")); if (commit->parents->next) @@ -261,7 +258,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) exit(128); if (result.clean) { - fprintf(stderr, "\nDone.\n"); strbuf_addf(&reflog_msg, "finish rebase %s onto %s", oid_to_hex(&last_picked_commit->object.oid), oid_to_hex(&last_commit->object.oid)); @@ -275,7 +271,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) die(_("unable to update HEAD")); } else { - fprintf(stderr, "\nAborting: Hit a conflict.\n"); strbuf_addf(&reflog_msg, "rebase progress up to %s", oid_to_hex(&last_picked_commit->object.oid)); if (update_ref(reflog_msg.buf, "HEAD", From patchwork Wed Nov 15 14:33:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456835 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 531123308B for ; Wed, 15 Nov 2023 14:34:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k5PIoP83" Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [IPv6:2a00:1450:4864:20::22a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF64818E for ; Wed, 15 Nov 2023 06:34:00 -0800 (PST) Received: by mail-lj1-x22a.google.com with SMTP id 38308e7fff4ca-2c50906f941so98291111fa.2 for ; Wed, 15 Nov 2023 06:34:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058838; x=1700663638; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KOdlaTs26TqwmEEb3Dw5BafzxV1HRx4XSvhePv1jFvQ=; b=k5PIoP83IyzDaoJ4+hdMG3R7I9T5vY1gEQ+cQ5cDIKF1hAvF/pkTu1XCVg7A+MVGaw 3o7cJfozaaNrurQ0Mwx+Mykvozy3w5zWpTFqw2ErlX+PB6/JuL++mBHr1NKSk81qfRBp 7ICiR8XO8K7PcTuVBZb5sBLKHbOhuTJ/qeuniRyN28xkn7N39Ts1SJogKZ4y8esX2t7j OHdFeCvz5Sbzp+tMTa/rwe9mmAeFMQ5kXoMn1YBWXRPqPs00DgVYeoIY5FRPBQ2DYeHZ w30FgH4uFpMWB68dfN8IRPs3g2VZN26P0PRapCHjdUG6wIc9DGyeCB4hJzvMN50SdIHP Chow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058838; x=1700663638; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KOdlaTs26TqwmEEb3Dw5BafzxV1HRx4XSvhePv1jFvQ=; b=LxuBPD57Zt/UB91eO1eVspu0F91UqSDAIv0ymEaIpzHlMHbLPmoRUqjrhNwB/SMAD8 Cw2LDcWh0kXhH9qRRk501yaDt62adeB0itj90tuwQyTwxEl6d6kOB5YXdJX6gYwVtb+m Br4mn+JE0d/CX9IliEJE1kt5L/DBAObnFjLMt86hyF6LqsnpFqW9cxXKwnT3BZXKksNn Kj5EsUnu+nAf0yYTjw0mvWKnJJYLl4w2vTvuEqz45G3HYfParupCCcu3/5jxoyh4Fv04 k+kxji9elAyid/nkr8HqaFxuQeYDcB04uVWv/fTUHzyKjdGEGqUSqNgsOix8r3BgBMo/ DRsg== X-Gm-Message-State: AOJu0Yw2MbI1ZqlMdNYedmtgEQYzCkgtDVNxoMxbcy4VeHTZ8Rgn6MiZ 1a9yVWjMz03TKTXU7QiSVKIJjBHOSxI= X-Google-Smtp-Source: AGHT+IH4Zaq9ipn1KEV0MCMdAPf4a9civ1BEbeO8gRGJOaJiboJdaCRbsuA5auasHQGzP2JsfH4Q4A== X-Received: by 2002:a2e:8810:0:b0:2c5:13e8:e6dc with SMTP id x16-20020a2e8810000000b002c513e8e6dcmr4205421ljh.31.1700058838292; Wed, 15 Nov 2023 06:33:58 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:57 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 09/14] replay: remove HEAD related sanity check Date: Wed, 15 Nov 2023 15:33:22 +0100 Message-ID: <20231115143327.2441397-10-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren We want replay to be a command that can be used on the server side on any branch, not just the current one, so we are going to stop updating HEAD in a future commit. A "sanity check" that makes sure we are replaying the current branch doesn't make sense anymore. Let's remove it. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 8 +------- t/t3650-replay-basics.sh | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index 1035435705..30292d219d 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -123,7 +123,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) struct commit *onto; const char *onto_name = NULL; struct commit *last_commit = NULL, *last_picked_commit = NULL; - struct object_id head; struct lock_file lock = LOCK_INIT; struct strvec rev_walk_args = STRVEC_INIT; struct rev_info revs; @@ -162,11 +161,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) onto = peel_committish(onto_name); strbuf_addf(&branch_name, "refs/heads/%s", argv[2]); - /* Sanity check */ - if (repo_get_oid(the_repository, "HEAD", &head)) - die(_("Cannot read HEAD")); - assert(oideq(&onto->object.oid, &head)); - repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR); if (repo_read_index(the_repository) < 0) BUG("Could not read index"); @@ -275,7 +269,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) oid_to_hex(&last_picked_commit->object.oid)); if (update_ref(reflog_msg.buf, "HEAD", &last_commit->object.oid, - &head, + &onto->object.oid, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { error(_("could not update %s"), argv[2]); die("Failed to update %s", argv[2]); diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index 36c1b5082a..b5b9f9ade2 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -48,8 +48,6 @@ test_expect_success 'setup' ' ' test_expect_success 'using replay to rebase two branches, one on top of other' ' - git switch main && - git replay --onto main topic1 topic2 >result && git log --format=%s $(cut -f 3 -d " " result) >actual && From patchwork Wed Nov 15 14:33:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456836 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4383633095 for ; Wed, 15 Nov 2023 14:34:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DcJltsJA" Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5BF6B187 for ; Wed, 15 Nov 2023 06:34:02 -0800 (PST) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4079ed65471so56372145e9.1 for ; Wed, 15 Nov 2023 06:34:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058840; x=1700663640; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eXL7yXRIHo5odRBwXpC0m0+J+flilNCNgYaQrjDxz1Y=; b=DcJltsJAgnNdvw/lF8IQJVBGKnT2nG3ogs03+NP4RNyNsJ0Zf5UwjGyoyzAZOXacP1 av7BowHbdXtIz5m7Qypp5fibSxFUoet9etuobEzjxqouIbAASYv68gmSgjeyYxiWfO8B TUTrls5b0N+pD97RzykIafTl7ebTLlM0j00XnMkyvAUISxxRyno4SQiKKqg7+z04PI+x 5RVqo3p2BAKevYkb2Xq4g3SIyK+tAMSXqkKJ5dMsQZV7I0mgfw9D5IGuX08tqHDGFpCB KeZyvvIHN2dYcFuVlmMljikZB6R+p7aEnycWqWN1QNE1kJ6bBlbjnuxv1zzPbVolArm3 2RyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058840; x=1700663640; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eXL7yXRIHo5odRBwXpC0m0+J+flilNCNgYaQrjDxz1Y=; b=gkgql8fGeRZ7NScLxglqLeIdbH7h/yXEjjuSy1BLxdP1kk/P3uEE1oDxSK9tB/TObl eJG0WZljl1+5qk58VFNcukkhNEQ0mEM+aD3bniRgx0M2r0ayLq7ssiBSOxuCsQSZEIMN 4LZL0f4miAmEaI91yw2uPrMv4ghnmqtuIi20CndycWPwh/X3SPmqf5rJnJAkAXtHxBdj nOSnXll4Wo0PiM19lsJl9zZSHfJ3XycFSrdT3NePBBvASsyibAjxKPSNKBfBL6FZnTPx LotHaFH9hX26i0kDXBkFbcRZWC5sQ17PAZFYk731au+ZxiiRjpFCc5SCpb/goT2EDOZC Alug== X-Gm-Message-State: AOJu0YwjsaeW0iNviAbgy9z9Ng4xMV2xIWcarxRNSUN7d2ZYsj2mrl13 owq4ExJ2Qutvf52wMVDqH9WLUkHabWc= X-Google-Smtp-Source: AGHT+IFDgq9AI2dPK6kgrPJeJuyVJXkxCE7bGDKIqWLjY2AfgrdnzHDmK4DfjvwsGaX4hOQ927juEg== X-Received: by 2002:a05:600c:3111:b0:405:36d7:4582 with SMTP id g17-20020a05600c311100b0040536d74582mr8535041wmo.15.1700058840288; Wed, 15 Nov 2023 06:34:00 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.33.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:33:58 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 10/14] replay: make it a minimal server side command Date: Wed, 15 Nov 2023 15:33:23 +0100 Message-ID: <20231115143327.2441397-11-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren We want this command to be a minimal command that just does server side picking of commits, displaying the results on stdout for higher level scripts to consume. So let's simplify it: * remove the worktree and index reading/writing, * remove the ref (and reflog) updating, * remove the assumptions tying us to HEAD, since (a) this is not a rebase and (b) we want to be able to pick commits in a bare repo, i.e. to/from branches that are not checked out and not the main branch, * remove unneeded includes, * handle rebasing multiple branches by printing on stdout the update ref commands that should be performed. The output can be piped into `git update-ref --stdin` for the ref updates to happen. In the future to make it easier for users to use this command directly maybe an option can be added to automatically pipe its output into `git update-ref`. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- Documentation/git-replay.txt | 5 +- builtin/replay.c | 78 ++++++++---------------- t/t3650-replay-basics.sh | 19 +++++- t/t6429-merge-sequence-rename-caching.sh | 39 +++++++----- 4 files changed, 72 insertions(+), 69 deletions(-) diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.txt index 0349058b66..87a85a7f57 100644 --- a/Documentation/git-replay.txt +++ b/Documentation/git-replay.txt @@ -15,7 +15,10 @@ DESCRIPTION ----------- Takes a range of commits, specified by and , and -replays them onto a new location (see `--onto` option below). +replays them onto a new location (see `--onto` option below). Leaves +the working tree and the index untouched, and updates no references. +The output of this command is meant to be used as input to +`git update-ref --stdin`, which would update the relevant branches. THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. diff --git a/builtin/replay.c b/builtin/replay.c index 30292d219d..73a25e9e85 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -6,11 +6,7 @@ #include "git-compat-util.h" #include "builtin.h" -#include "cache-tree.h" -#include "commit.h" #include "environment.h" -#include "gettext.h" -#include "hash.h" #include "hex.h" #include "lockfile.h" #include "merge-ort.h" @@ -18,8 +14,6 @@ #include "parse-options.h" #include "refs.h" #include "revision.h" -#include "sequencer.h" -#include "setup.h" #include "strvec.h" #include #include @@ -102,6 +96,7 @@ static struct commit *pick_regular_commit(struct commit *pickme, pickme_tree = repo_get_commit_tree(the_repository, pickme); base_tree = repo_get_commit_tree(the_repository, base); + merge_opt->branch1 = short_commit_name(last_commit); merge_opt->branch2 = short_commit_name(pickme); merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2); @@ -122,15 +117,12 @@ int cmd_replay(int argc, const char **argv, const char *prefix) { struct commit *onto; const char *onto_name = NULL; - struct commit *last_commit = NULL, *last_picked_commit = NULL; - struct lock_file lock = LOCK_INIT; + struct commit *last_commit = NULL; struct strvec rev_walk_args = STRVEC_INIT; struct rev_info revs; struct commit *commit; struct merge_options merge_opt; - struct tree *head_tree; struct merge_result result; - struct strbuf reflog_msg = STRBUF_INIT; struct strbuf branch_name = STRBUF_INIT; int ret = 0; @@ -161,10 +153,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) onto = peel_committish(onto_name); strbuf_addf(&branch_name, "refs/heads/%s", argv[2]); - repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR); - if (repo_read_index(the_repository) < 0) - BUG("Could not read index"); - repo_init_revisions(the_repository, &revs, prefix); strvec_pushl(&rev_walk_args, "", argv[2], "--not", argv[1], NULL); @@ -227,58 +215,44 @@ int cmd_replay(int argc, const char **argv, const char *prefix) init_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; - merge_opt.branch1 = "HEAD"; - head_tree = repo_get_commit_tree(the_repository, onto); - result.tree = head_tree; + result.tree = repo_get_commit_tree(the_repository, onto); last_commit = onto; while ((commit = get_revision(&revs))) { - struct commit *pick; + const struct name_decoration *decoration; if (!commit->parents) die(_("replaying down to root commit is not supported yet!")); if (commit->parents->next) die(_("replaying merge commits is not supported yet!")); - pick = pick_regular_commit(commit, last_commit, &merge_opt, &result); - if (!pick) + last_commit = pick_regular_commit(commit, last_commit, &merge_opt, &result); + if (!last_commit) break; - last_commit = pick; - last_picked_commit = commit; + + decoration = get_name_decoration(&commit->object); + if (!decoration) + continue; + + while (decoration) { + if (decoration->type == DECORATION_REF_LOCAL) { + printf("update %s %s %s\n", + decoration->name, + oid_to_hex(&last_commit->object.oid), + oid_to_hex(&commit->object.oid)); + } + decoration = decoration->next; + } } merge_finalize(&merge_opt, &result); + ret = result.clean; - if (result.clean < 0) - exit(128); - - if (result.clean) { - strbuf_addf(&reflog_msg, "finish rebase %s onto %s", - oid_to_hex(&last_picked_commit->object.oid), - oid_to_hex(&last_commit->object.oid)); - if (update_ref(reflog_msg.buf, branch_name.buf, - &last_commit->object.oid, - &last_picked_commit->object.oid, - REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[2]); - die("Failed to update %s", argv[2]); - } - if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) - die(_("unable to update HEAD")); - } else { - strbuf_addf(&reflog_msg, "rebase progress up to %s", - oid_to_hex(&last_picked_commit->object.oid)); - if (update_ref(reflog_msg.buf, "HEAD", - &last_commit->object.oid, - &onto->object.oid, - REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[2]); - die("Failed to update %s", argv[2]); - } - } - ret = (result.clean == 0); cleanup: - strbuf_release(&reflog_msg); strbuf_release(&branch_name); release_revisions(&revs); - return ret; + + /* Return */ + if (ret < 0) + exit(128); + return ret ? 0 : 1; } diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index b5b9f9ade2..3567c98362 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -47,12 +47,29 @@ test_expect_success 'setup' ' test_commit C.conflict C.t conflict ' +test_expect_success 'setup bare' ' + git clone --bare . bare +' + test_expect_success 'using replay to rebase two branches, one on top of other' ' git replay --onto main topic1 topic2 >result && + test_line_count = 1 result && + git log --format=%s $(cut -f 3 -d " " result) >actual && test_write_lines E D M L B A >expect && - test_cmp expect actual + test_cmp expect actual && + + printf "update refs/heads/topic2 " >expect && + printf "%s " $(cut -f 3 -d " " result) >>expect && + git rev-parse topic2 >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to rebase two branches, one on top of other' ' + git -C bare replay --onto main topic1 topic2 >result-bare && + test_cmp expect result-bare ' test_done diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index 7670b72008..099aefeffc 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -71,8 +71,9 @@ test_expect_success 'caching renames does not preclude finding new ones' ' git switch upstream && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin tracked-files && test_line_count = 2 tracked-files && @@ -140,7 +141,9 @@ test_expect_success 'cherry-pick both a commit and its immediate revert' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 1 calls @@ -198,8 +201,9 @@ test_expect_success 'rename same file identically, then reintroduce it' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin tracked && test_line_count = 2 tracked && @@ -275,8 +279,9 @@ test_expect_success 'rename same file identically, then add file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin tracked && test_line_count = 4 tracked && @@ -451,8 +456,9 @@ test_expect_success 'dir rename unneeded, then add new file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 2 calls && @@ -517,8 +523,9 @@ test_expect_success 'dir rename unneeded, then rename existing file into old dir GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 3 calls && @@ -619,8 +626,9 @@ test_expect_success 'caching renames only on upstream side, part 1' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 1 calls && @@ -677,8 +685,9 @@ test_expect_success 'caching renames only on upstream side, part 2' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic && - git reset --hard topic && + git replay --onto HEAD upstream~1 topic >out && + git update-ref --stdin calls && test_line_count = 2 calls && From patchwork Wed Nov 15 14:33:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456837 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A89FE2F505 for ; Wed, 15 Nov 2023 14:34:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aAvgLWLL" Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0D6C189 for ; Wed, 15 Nov 2023 06:34:04 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-4083ac51d8aso56273245e9.2 for ; Wed, 15 Nov 2023 06:34:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058842; x=1700663642; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rJ1KHOi4XTx8OsKdmk51H2m4FbYVMHOhT7aCL4Dis80=; b=aAvgLWLLTe9Y3Lsvy6BUN17ZzjzVAIrsGNdy9k7gm7IjPK1S1mR/8NEKdiPNc4EyAP vHLAXEwe+iidvuj/1aatmegAXfsFNB0JeyCj4Fc54lF6jjwuAOhQHfS0k09jCWWcfVK7 TYIzcEadYr+lcWUiBhOcaO3s7rD+Dya8Z+K6vgQXCObfGvoOlbIhdeCl0OqoeNUejoHu G1S7ab4oASzJpozI5sua8C/hTHcf/VQZvv46O+YBdWl7cijBAO4YdxVNEqv60MQ7hY6/ PMihI25ekeJ3QQXi2wx8DgwQUbG3WJ3Rpkb/VHvfTUxJjjqOX/C+7k6729kbTy5DQWEh 485g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058842; x=1700663642; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rJ1KHOi4XTx8OsKdmk51H2m4FbYVMHOhT7aCL4Dis80=; b=aWPtb2HWZyYb+80QbYv88GLIV4qUGtXTrcQULmt+oEVboV6ugsPbP6PgtAkpIz6JsI xpQMTRnmqAYX7xvP9cUg+1EZNj6kKe8gMiUleOYc4ZUt9RkixSUxNDgG9wcWe0Gj7xxm NYhffjC/oFev+k/g5kqhd2ONfG3rmwDoGSgKb6W2c86ixAjc7PfeTDRL71doE/8yTaCE lh1brL4m6hxyJGNngyadsT6d+imL7P0dWVkNugzXiO+bWc8IKml7bbu9qMB11bjHPbvi NmjqxR3o4xuSiQBXBYC2T6bTD/c+LSbc5QWxkZZ3MP1jCcKsD5xRzTvE9fQIBVHo2R6y I5+A== X-Gm-Message-State: AOJu0YzPFTX+uTjBGTMld/mjITHeHfcnu9Tl1MSDyPTzUn3bnKJID+Jk 4UR7vMKr/8F275WDEZTpP4t0u9rbwcw= X-Google-Smtp-Source: AGHT+IGQ9cZy14yw1nIV6nMzvNKTNPuxCrD2YC6uAorA4rhi4a7oYo3oqXKxyzOnRNY2gFUNdch2Qg== X-Received: by 2002:a05:600c:893:b0:40a:437e:30fd with SMTP id l19-20020a05600c089300b0040a437e30fdmr9344241wmp.9.1700058841758; Wed, 15 Nov 2023 06:34:01 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.34.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:34:00 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 11/14] replay: use standard revision ranges Date: Wed, 15 Nov 2023 15:33:24 +0100 Message-ID: <20231115143327.2441397-12-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren Instead of the fixed " " arguments, the replay command now accepts "..." arguments in a similar way as many other Git commands. This makes its interface more standard and more flexible. This also enables many revision related options accepted and eaten by setup_revisions(). If the replay command was a high level one or had a high level mode, it would make sense to restrict some of the possible options, like those generating non-contiguous history, as they could be confusing for most users. Also as the interface of the command is now mostly finalized, we can add more documentation and more testcases to make sure the command will continue to work as designed in the future. We only document the rev-list related options among all the revision related options that are now accepted, as the rev-list related ones are probably the most useful for now. Helped-by: Dragan Simic Helped-by: Linus Arver Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- Documentation/git-replay.txt | 58 ++++++++++++++++++++++-- builtin/replay.c | 21 ++------- t/t3650-replay-basics.sh | 12 ++++- t/t6429-merge-sequence-rename-caching.sh | 18 ++++---- 4 files changed, 77 insertions(+), 32 deletions(-) diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.txt index 87a85a7f57..fab4ea0178 100644 --- a/Documentation/git-replay.txt +++ b/Documentation/git-replay.txt @@ -9,16 +9,16 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t SYNOPSIS -------- [verse] -'git replay' --onto # EXPERIMENTAL +'git replay' --onto ... # EXPERIMENTAL DESCRIPTION ----------- -Takes a range of commits, specified by and , and -replays them onto a new location (see `--onto` option below). Leaves +Takes ranges of commits and replays them onto a new location. Leaves the working tree and the index untouched, and updates no references. The output of this command is meant to be used as input to -`git update-ref --stdin`, which would update the relevant branches. +`git update-ref --stdin`, which would update the relevant branches +(see the OUTPUT section below). THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. @@ -28,6 +28,30 @@ OPTIONS --onto :: Starting point at which to create the new commits. May be any valid commit, and not just an existing branch name. ++ +The update-ref command(s) in the output will update the branch(es) in +the revision range to point at the new commits, similar to the way how +`git rebase --update-refs` updates multiple branches in the affected +range. + +:: + Range of commits to replay; see "Specifying Ranges" in + linkgit:git-rev-parse and the "Commit Limiting" options below. + +include::rev-list-options.txt[] + +OUTPUT +------ + +When there are no conflicts, the output of this command is usable as +input to `git update-ref --stdin`. It is of the form: + + update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH} + update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH} + update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH} + +where the number of refs updated depends on the arguments passed and +the shape of the history being replayed. EXIT STATUS ----------- @@ -37,6 +61,32 @@ the replay has conflicts, the exit status is 1. If the replay is not able to complete (or start) due to some kind of error, the exit status is something other than 0 or 1. +EXAMPLES +-------- + +To simply rebase `mybranch` onto `target`: + +------------ +$ git replay --onto target origin/main..mybranch +update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH} +------------ + +When calling `git replay`, one does not need to specify a range of +commits to replay using the syntax `A..B`; any range expression will +do: + +------------ +$ git replay --onto origin/main ^base branch1 branch2 branch3 +update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH} +update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH} +update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH} +------------ + +This will simultaneously rebase `branch1`, `branch2`, and `branch3`, +all commits they have since `base`, playing them on top of +`origin/main`. These three branches may have commits on top of `base` +that they have in common, but that does not need to be the case. + GIT --- Part of the linkgit:git[1] suite diff --git a/builtin/replay.c b/builtin/replay.c index 73a25e9e85..7a660020d1 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -14,7 +14,6 @@ #include "parse-options.h" #include "refs.h" #include "revision.h" -#include "strvec.h" #include #include @@ -118,16 +117,14 @@ int cmd_replay(int argc, const char **argv, const char *prefix) struct commit *onto; const char *onto_name = NULL; struct commit *last_commit = NULL; - struct strvec rev_walk_args = STRVEC_INIT; struct rev_info revs; struct commit *commit; struct merge_options merge_opt; struct merge_result result; - struct strbuf branch_name = STRBUF_INIT; int ret = 0; const char * const replay_usage[] = { - N_("git replay --onto # EXPERIMENTAL"), + N_("git replay --onto ... # EXPERIMENTAL"), NULL }; struct option replay_options[] = { @@ -145,18 +142,10 @@ int cmd_replay(int argc, const char **argv, const char *prefix) usage_with_options(replay_usage, replay_options); } - if (argc != 3) { - error(_("bad number of arguments")); - usage_with_options(replay_usage, replay_options); - } - onto = peel_committish(onto_name); - strbuf_addf(&branch_name, "refs/heads/%s", argv[2]); repo_init_revisions(the_repository, &revs, prefix); - strvec_pushl(&rev_walk_args, "", argv[2], "--not", argv[1], NULL); - /* * Set desired values for rev walking options here. If they * are changed by some user specified option in setup_revisions() @@ -171,8 +160,9 @@ int cmd_replay(int argc, const char **argv, const char *prefix) revs.topo_order = 1; revs.simplify_history = 0; - if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) { - ret = error(_("unhandled options")); + argc = setup_revisions(argc, argv, &revs, NULL); + if (argc > 1) { + ret = error(_("unrecognized argument: %s"), argv[1]); goto cleanup; } @@ -205,8 +195,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) revs.simplify_history = 0; } - strvec_clear(&rev_walk_args); - if (prepare_revision_walk(&revs) < 0) { ret = error(_("error preparing revisions")); goto cleanup; @@ -248,7 +236,6 @@ int cmd_replay(int argc, const char **argv, const char *prefix) ret = result.clean; cleanup: - strbuf_release(&branch_name); release_revisions(&revs); /* Return */ diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index 3567c98362..a1da4f9ef9 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -52,7 +52,7 @@ test_expect_success 'setup bare' ' ' test_expect_success 'using replay to rebase two branches, one on top of other' ' - git replay --onto main topic1 topic2 >result && + git replay --onto main topic1..topic2 >result && test_line_count = 1 result && @@ -68,8 +68,16 @@ test_expect_success 'using replay to rebase two branches, one on top of other' ' ' test_expect_success 'using replay on bare repo to rebase two branches, one on top of other' ' - git -C bare replay --onto main topic1 topic2 >result-bare && + git -C bare replay --onto main topic1..topic2 >result-bare && test_cmp expect result-bare ' +test_expect_success 'using replay to rebase with a conflict' ' + test_expect_code 1 git replay --onto topic1 B..conflict +' + +test_expect_success 'using replay on bare repo to rebase with a conflict' ' + test_expect_code 1 git -C bare replay --onto topic1 B..conflict +' + test_done diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index 099aefeffc..0f39ed0d08 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -71,7 +71,7 @@ test_expect_success 'caching renames does not preclude finding new ones' ' git switch upstream && - git replay --onto HEAD upstream~1 topic >out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin output && + test_must_fail git replay --onto HEAD upstream~1..topic >output && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls @@ -456,7 +456,7 @@ test_expect_success 'dir rename unneeded, then add new file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - git replay --onto HEAD upstream~1 topic >out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin out && + git replay --onto HEAD upstream~1..topic >out && git update-ref --stdin X-Patchwork-Id: 13456838 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E6093307F for ; Wed, 15 Nov 2023 14:34:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GnFFZs99" Received: from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com [IPv6:2a00:1450:4864:20::12d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D296418B for ; Wed, 15 Nov 2023 06:34:05 -0800 (PST) Received: by mail-lf1-x12d.google.com with SMTP id 2adb3069b0e04-50970c2115eso9650688e87.1 for ; Wed, 15 Nov 2023 06:34:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058843; x=1700663643; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/SWWpVY1QOXJjKBVdtuvVqPdlbyldOkUj6TjIl7NecM=; b=GnFFZs99PT3kXu95l3VmiEtlWUoerrOMJ2FWUdteQUZRC9Wd6hI18XCmL3INFpJ0XO H+tXlVxtmn8v3w8SdcMX1n4ueuM8DGARCQz2zoVKRkNmVx7IeYuS+bXRbQ7OjDaNs4me BtsEGOb+RkEQVKzOBtt/DOJPlOMhiT8B7N9no4kIGx3ZGqKrLXnUHl6BIlFeECpp+0fg j3Cvxpgv9YYE2YIT4G+n+2606OcfqD9Tl9mkKamNgtNqJs+/e2DtKKgx3TBjcUyIUMl5 hT+Yiv/PzNkm8kdOYVpBBeQhErW5vTBnkMYjPN0NEmPOeXsF9EiSsBaUk1tj4xsFRMIg kjjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058843; x=1700663643; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/SWWpVY1QOXJjKBVdtuvVqPdlbyldOkUj6TjIl7NecM=; b=a3steL5Y0AVDm0MnNKeO7r7DT0137nMWuDHAp/FTODufAuPFthV8UhzEssHtx4lLh3 B3iilfk+Vl0QI6mcjg4+C733+Jc/F+KqEttubMs/xWIFlkOXgzR3MEYjEcAqP+z2kBs/ mWMVBFW2q+RTVuC1o9zI7qdUx7Y8AgFaa88KyMahLNuWEgoYKuX5DM12+oTPkq1lCyxC PoCu5GAZ/oln1Oueyfu2jJ0lw7nxiJGW5q+U4b5luw7lQlb8Z6ObYHs7a8af92uJxxhV KQjJsjHVAwEivYZw0z01ZgvStOXNt0G0GGndcJfApnpZDiaslyiT9ys3bK12F16L9wEH AvRg== X-Gm-Message-State: AOJu0Yybeogpr4WKVhePL39Lw8/5F6PWqgkDIRWQKKnABlzss8b9HgH+ 7mgf3+siytCqf/iej90uzbK06JBRgAk= X-Google-Smtp-Source: AGHT+IGCv3Zz/9kADgAA1HT0YirM7fIkRaRb0vjxMucr6SPRfiqkDcjLDq+vp6+ZU8OfL3OKkUtbqQ== X-Received: by 2002:a2e:5c02:0:b0:2c5:70e:734a with SMTP id q2-20020a2e5c02000000b002c5070e734amr3493447ljb.2.1700058842678; Wed, 15 Nov 2023 06:34:02 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:34:02 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 12/14] replay: add --advance or 'cherry-pick' mode Date: Wed, 15 Nov 2023 15:33:25 +0100 Message-ID: <20231115143327.2441397-13-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren There is already a 'rebase' mode with `--onto`. Let's add an 'advance' or 'cherry-pick' mode with `--advance`. This new mode will make the target branch advance as we replay commits onto it. The replayed commits should have a single tip, so that it's clear where the target branch should be advanced. If they have more than one tip, this new mode will error out. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- Documentation/git-replay.txt | 41 ++++++-- builtin/replay.c | 185 +++++++++++++++++++++++++++++++++-- t/t3650-replay-basics.sh | 34 +++++++ 3 files changed, 243 insertions(+), 17 deletions(-) diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.txt index fab4ea0178..6daa5b4275 100644 --- a/Documentation/git-replay.txt +++ b/Documentation/git-replay.txt @@ -9,7 +9,7 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t SYNOPSIS -------- [verse] -'git replay' --onto ... # EXPERIMENTAL +'git replay' (--onto | --advance ) ... # EXPERIMENTAL DESCRIPTION ----------- @@ -29,14 +29,25 @@ OPTIONS Starting point at which to create the new commits. May be any valid commit, and not just an existing branch name. + -The update-ref command(s) in the output will update the branch(es) in -the revision range to point at the new commits, similar to the way how -`git rebase --update-refs` updates multiple branches in the affected -range. +When `--onto` is specified, the update-ref command(s) in the output will +update the branch(es) in the revision range to point at the new +commits, similar to the way how `git rebase --update-refs` updates +multiple branches in the affected range. + +--advance :: + Starting point at which to create the new commits; must be a + branch name. ++ +When `--advance` is specified, the update-ref command(s) in the output +will update the branch passed as an argument to `--advance` to point at +the new commits (in other words, this mimics a cherry-pick operation). :: - Range of commits to replay; see "Specifying Ranges" in - linkgit:git-rev-parse and the "Commit Limiting" options below. + Range of commits to replay. More than one can + be passed, but in `--advance ` mode, they should have + a single tip, so that it's clear where should point + to. See "Specifying Ranges" in linkgit:git-rev-parse and the + "Commit Limiting" options below. include::rev-list-options.txt[] @@ -51,7 +62,9 @@ input to `git update-ref --stdin`. It is of the form: update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH} where the number of refs updated depends on the arguments passed and -the shape of the history being replayed. +the shape of the history being replayed. When using `--advance`, the +number of refs updated is always one, but for `--onto`, it can be one +or more (rebasing multiple branches simultaneously is supported). EXIT STATUS ----------- @@ -71,6 +84,18 @@ $ git replay --onto target origin/main..mybranch update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH} ------------ +To cherry-pick the commits from mybranch onto target: + +------------ +$ git replay --advance target origin/main..mybranch +update refs/heads/target ${NEW_target_HASH} ${OLD_target_HASH} +------------ + +Note that the first two examples replay the exact same commits and on +top of the exact same new base, they only differ in that the first +provides instructions to make mybranch point at the new commits and +the second provides instructions to make target point at them. + When calling `git replay`, one does not need to specify a range of commits to replay using the syntax `A..B`; any range expression will do: diff --git a/builtin/replay.c b/builtin/replay.c index 7a660020d1..1a419cb7fd 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -14,6 +14,7 @@ #include "parse-options.h" #include "refs.h" #include "revision.h" +#include "strmap.h" #include #include @@ -82,6 +83,146 @@ static struct commit *create_commit(struct tree *tree, return (struct commit *)obj; } +struct ref_info { + struct commit *onto; + struct strset positive_refs; + struct strset negative_refs; + int positive_refexprs; + int negative_refexprs; +}; + +static void get_ref_information(struct rev_cmdline_info *cmd_info, + struct ref_info *ref_info) +{ + int i; + + ref_info->onto = NULL; + strset_init(&ref_info->positive_refs); + strset_init(&ref_info->negative_refs); + ref_info->positive_refexprs = 0; + ref_info->negative_refexprs = 0; + + /* + * When the user specifies e.g. + * git replay origin/main..mybranch + * git replay ^origin/next mybranch1 mybranch2 + * we want to be able to determine where to replay the commits. In + * these examples, the branches are probably based on an old version + * of either origin/main or origin/next, so we want to replay on the + * newest version of that branch. In contrast we would want to error + * out if they ran + * git replay ^origin/master ^origin/next mybranch + * git replay mybranch~2..mybranch + * the first of those because there's no unique base to choose, and + * the second because they'd likely just be replaying commits on top + * of the same commit and not making any difference. + */ + for (i = 0; i < cmd_info->nr; i++) { + struct rev_cmdline_entry *e = cmd_info->rev + i; + struct object_id oid; + const char *refexpr = e->name; + char *fullname = NULL; + int can_uniquely_dwim = 1; + + if (*refexpr == '^') + refexpr++; + if (repo_dwim_ref(the_repository, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1) + can_uniquely_dwim = 0; + + if (e->flags & BOTTOM) { + if (can_uniquely_dwim) + strset_add(&ref_info->negative_refs, fullname); + if (!ref_info->negative_refexprs) + ref_info->onto = lookup_commit_reference_gently(the_repository, + &e->item->oid, 1); + ref_info->negative_refexprs++; + } else { + if (can_uniquely_dwim) + strset_add(&ref_info->positive_refs, fullname); + ref_info->positive_refexprs++; + } + + free(fullname); + } +} + +static void determine_replay_mode(struct rev_cmdline_info *cmd_info, + const char *onto_name, + const char **advance_name, + struct commit **onto, + struct strset **update_refs) +{ + struct ref_info rinfo; + + get_ref_information(cmd_info, &rinfo); + if (!rinfo.positive_refexprs) + die(_("need some commits to replay")); + if (onto_name && *advance_name) + die(_("--onto and --advance are incompatible")); + else if (onto_name) { + *onto = peel_committish(onto_name); + if (rinfo.positive_refexprs < + strset_get_size(&rinfo.positive_refs)) + die(_("all positive revisions given must be references")); + } else if (*advance_name) { + struct object_id oid; + char *fullname = NULL; + + *onto = peel_committish(*advance_name); + if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name), + &oid, &fullname, 0) == 1) { + *advance_name = fullname; + } else { + die(_("argument to --advance must be a reference")); + } + if (rinfo.positive_refexprs > 1) + die(_("cannot advance target with multiple sources because ordering would be ill-defined")); + } else { + int positive_refs_complete = ( + rinfo.positive_refexprs == + strset_get_size(&rinfo.positive_refs)); + int negative_refs_complete = ( + rinfo.negative_refexprs == + strset_get_size(&rinfo.negative_refs)); + /* + * We need either positive_refs_complete or + * negative_refs_complete, but not both. + */ + if (rinfo.negative_refexprs > 0 && + positive_refs_complete == negative_refs_complete) + die(_("cannot implicitly determine whether this is an --advance or --onto operation")); + if (negative_refs_complete) { + struct hashmap_iter iter; + struct strmap_entry *entry; + + if (rinfo.negative_refexprs == 0) + die(_("all positive revisions given must be references")); + else if (rinfo.negative_refexprs > 1) + die(_("cannot implicitly determine whether this is an --advance or --onto operation")); + else if (rinfo.positive_refexprs > 1) + die(_("cannot advance target with multiple source branches because ordering would be ill-defined")); + + /* Only one entry, but we have to loop to get it */ + strset_for_each_entry(&rinfo.negative_refs, + &iter, entry) { + *advance_name = entry->key; + } + } else { /* positive_refs_complete */ + if (rinfo.negative_refexprs > 1) + die(_("cannot implicitly determine correct base for --onto")); + if (rinfo.negative_refexprs == 1) + *onto = rinfo.onto; + } + } + if (!*advance_name) { + *update_refs = xcalloc(1, sizeof(**update_refs)); + **update_refs = rinfo.positive_refs; + memset(&rinfo.positive_refs, 0, sizeof(**update_refs)); + } + strset_clear(&rinfo.negative_refs); + strset_clear(&rinfo.positive_refs); +} + static struct commit *pick_regular_commit(struct commit *pickme, struct commit *last_commit, struct merge_options *merge_opt, @@ -114,20 +255,26 @@ static struct commit *pick_regular_commit(struct commit *pickme, int cmd_replay(int argc, const char **argv, const char *prefix) { - struct commit *onto; + const char *advance_name = NULL; + struct commit *onto = NULL; const char *onto_name = NULL; - struct commit *last_commit = NULL; + struct rev_info revs; + struct commit *last_commit = NULL; struct commit *commit; struct merge_options merge_opt; struct merge_result result; + struct strset *update_refs = NULL; int ret = 0; const char * const replay_usage[] = { - N_("git replay --onto ... # EXPERIMENTAL"), + N_("git replay (--onto | --advance ) ... # EXPERIMENTAL"), NULL }; struct option replay_options[] = { + OPT_STRING(0, "advance", &advance_name, + N_("branch"), + N_("make replay advance given branch")), OPT_STRING(0, "onto", &onto_name, N_("revision"), N_("replay onto given commit")), @@ -137,13 +284,11 @@ int cmd_replay(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, replay_options, replay_usage, PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT); - if (!onto_name) { - error(_("option --onto is mandatory")); + if (!onto_name && !advance_name) { + error(_("option --onto or --advance is mandatory")); usage_with_options(replay_usage, replay_options); } - onto = peel_committish(onto_name); - repo_init_revisions(the_repository, &revs, prefix); /* @@ -195,6 +340,12 @@ int cmd_replay(int argc, const char **argv, const char *prefix) revs.simplify_history = 0; } + determine_replay_mode(&revs.cmdline, onto_name, &advance_name, + &onto, &update_refs); + + if (!onto) /* FIXME: Should handle replaying down to root commit */ + die("Replaying down to root commit is not supported yet!"); + if (prepare_revision_walk(&revs) < 0) { ret = error(_("error preparing revisions")); goto cleanup; @@ -203,6 +354,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) init_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; + result.tree = repo_get_commit_tree(the_repository, onto); last_commit = onto; while ((commit = get_revision(&revs))) { @@ -217,12 +369,15 @@ int cmd_replay(int argc, const char **argv, const char *prefix) if (!last_commit) break; + /* Update any necessary branches */ + if (advance_name) + continue; decoration = get_name_decoration(&commit->object); if (!decoration) continue; - while (decoration) { - if (decoration->type == DECORATION_REF_LOCAL) { + if (decoration->type == DECORATION_REF_LOCAL && + strset_contains(update_refs, decoration->name)) { printf("update %s %s %s\n", decoration->name, oid_to_hex(&last_commit->object.oid), @@ -232,10 +387,22 @@ int cmd_replay(int argc, const char **argv, const char *prefix) } } + /* In --advance mode, advance the target ref */ + if (result.clean == 1 && advance_name) { + printf("update %s %s %s\n", + advance_name, + oid_to_hex(&last_commit->object.oid), + oid_to_hex(&onto->object.oid)); + } + merge_finalize(&merge_opt, &result); ret = result.clean; cleanup: + if (update_refs) { + strset_clear(update_refs); + free(update_refs); + } release_revisions(&revs); /* Return */ diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index a1da4f9ef9..68a87e7803 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -80,4 +80,38 @@ test_expect_success 'using replay on bare repo to rebase with a conflict' ' test_expect_code 1 git -C bare replay --onto topic1 B..conflict ' +test_expect_success 'using replay to perform basic cherry-pick' ' + # The differences between this test and previous ones are: + # --advance vs --onto + # 2nd field of result is refs/heads/main vs. refs/heads/topic2 + # 4th field of result is hash for main instead of hash for topic2 + + git replay --advance main topic1..topic2 >result && + + test_line_count = 1 result && + + git log --format=%s $(cut -f 3 -d " " result) >actual && + test_write_lines E D M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/main " >expect && + printf "%s " $(cut -f 3 -d " " result) >>expect && + git rev-parse main >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to perform basic cherry-pick' ' + git -C bare replay --advance main topic1..topic2 >result-bare && + test_cmp expect result-bare +' + +test_expect_success 'replay on bare repo fails with both --advance and --onto' ' + test_must_fail git -C bare replay --advance main --onto main topic1..topic2 >result-bare +' + +test_expect_success 'replay fails when both --advance and --onto are omitted' ' + test_must_fail git replay topic1..topic2 >result +' + test_done From patchwork Wed Nov 15 14:33:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456839 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C09D33095 for ; Wed, 15 Nov 2023 14:34:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Rona1yuQ" Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7134B18D for ; Wed, 15 Nov 2023 06:34:07 -0800 (PST) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4084b0223ccso53569645e9.2 for ; Wed, 15 Nov 2023 06:34:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058845; x=1700663645; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Y4zd/oScWv0eVySkwahsDIwB3AHXeq3kAyFFQOU+wro=; b=Rona1yuQuQ/MQwusHo0oDhX8zeD1FJl3o/gbpih7YleFw+8MIdRtESReqkkUAvApyD PSWXnAjiv0wFC9aDfynui8bL+7aUqlrjRbm/i9Wz4TE8MIbH+We3f2z+t98ibLtgggUn EUCXj1DublILzUUidjYHiLTqCVyyTeQce6IEWB9OqfP6kcuUDq1nP7+TrAYQlLGJ7l1Z S7RKDCFAPEoNufwMtJkT8j7ZSVKK15aHf08WHHMxJCc9LAjOwrDbdsbI+pEa7oedTjxq KdYNIXrHYO6uXU/W5W0K4Avv1T102xFfNCOGS+W7N8Z3lHq0xkE54I6cwRyoU9W+ZXYx ohlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058845; x=1700663645; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y4zd/oScWv0eVySkwahsDIwB3AHXeq3kAyFFQOU+wro=; b=v2lU3uCeAy1sc5G+H0DQN2eZmR7h6SxId5P0GXjW4jk8R8A8yV4wlLYC70Daq1Qlw6 TevgA6o8VH0g6mYApG8Ul2y4o38imn7RpJ5cYJFNLcoqqMElsmbpAoBLKAfIOsNfDbuH fAOmn6+IEe/X5JljqzyodaQ+4U/dSxbxQrWhzhSuxJ1czP1xG+1S303FPFy39fmc6nbV DoAIaiGrvwwfPuz2E44q4HJoK4U9l65o9SXUxesjlaUUEHFRtg4RiyKU4K5uCjf2h/RJ vOxTq56vU6x2M+Zr5MUGvXHEOgHrHS7vT97m+a4bjrDwfO4GGZRVhhYqpaJB8a9HxQ3o SchA== X-Gm-Message-State: AOJu0YxNFNeLZRxufm6EVVek3kD7DXkFHl2dO+RnsWtXOPwzLYHeK9uk SOWiAIQd8s2EqojHQywTlqHJA79lpQc= X-Google-Smtp-Source: AGHT+IFMmJryh7567TG6Uxavg7gL51TrFUXeIdfvLoGEplaKFF3pMIA5q5UGY6C7VfteKSqsNmT/lA== X-Received: by 2002:a05:600c:1f87:b0:40a:55a6:793a with SMTP id je7-20020a05600c1f8700b0040a55a6793amr6212813wmb.21.1700058845010; Wed, 15 Nov 2023 06:34:05 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.34.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:34:03 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 13/14] replay: add --contained to rebase contained branches Date: Wed, 15 Nov 2023 15:33:26 +0100 Message-ID: <20231115143327.2441397-14-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren Let's add a `--contained` option that can be used along with `--onto` to rebase all the branches contained in the argument. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- Documentation/git-replay.txt | 12 +++++++++++- builtin/replay.c | 13 +++++++++++-- t/t3650-replay-basics.sh | 29 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.txt index 6daa5b4275..133d7af9ee 100644 --- a/Documentation/git-replay.txt +++ b/Documentation/git-replay.txt @@ -9,7 +9,7 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t SYNOPSIS -------- [verse] -'git replay' (--onto | --advance ) ... # EXPERIMENTAL +'git replay' ([--contained] --onto | --advance ) ... # EXPERIMENTAL DESCRIPTION ----------- @@ -96,6 +96,16 @@ top of the exact same new base, they only differ in that the first provides instructions to make mybranch point at the new commits and the second provides instructions to make target point at them. +What if you have a stack of branches, one depending upon another, and +you'd really like to rebase the whole set? + +------------ +$ git replay --contained --onto origin/main origin/main..tipbranch +update refs/heads/branch1 ${NEW_branch1_HASH} ${OLD_branch1_HASH} +update refs/heads/branch2 ${NEW_branch2_HASH} ${OLD_branch2_HASH} +update refs/heads/tipbranch ${NEW_tipbranch_HASH} ${OLD_tipbranch_HASH} +------------ + When calling `git replay`, one does not need to specify a range of commits to replay using the syntax `A..B`; any range expression will do: diff --git a/builtin/replay.c b/builtin/replay.c index 1a419cb7fd..e14e33bcc5 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -258,6 +258,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) const char *advance_name = NULL; struct commit *onto = NULL; const char *onto_name = NULL; + int contained = 0; struct rev_info revs; struct commit *last_commit = NULL; @@ -268,7 +269,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix) int ret = 0; const char * const replay_usage[] = { - N_("git replay (--onto | --advance ) ... # EXPERIMENTAL"), + N_("git replay ([--contained] --onto | --advance ) " + "... # EXPERIMENTAL"), NULL }; struct option replay_options[] = { @@ -278,6 +280,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix) OPT_STRING(0, "onto", &onto_name, N_("revision"), N_("replay onto given commit")), + OPT_BOOL(0, "contained", &contained, + N_("advance all branches contained in revision-range")), OPT_END() }; @@ -289,6 +293,10 @@ int cmd_replay(int argc, const char **argv, const char *prefix) usage_with_options(replay_usage, replay_options); } + if (advance_name && contained) + die(_("options '%s' and '%s' cannot be used together"), + "--advance", "--contained"); + repo_init_revisions(the_repository, &revs, prefix); /* @@ -377,7 +385,8 @@ int cmd_replay(int argc, const char **argv, const char *prefix) continue; while (decoration) { if (decoration->type == DECORATION_REF_LOCAL && - strset_contains(update_refs, decoration->name)) { + (contained || strset_contains(update_refs, + decoration->name))) { printf("update %s %s %s\n", decoration->name, oid_to_hex(&last_commit->object.oid), diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index 68a87e7803..d6286f9580 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -114,4 +114,33 @@ test_expect_success 'replay fails when both --advance and --onto are omitted' ' test_must_fail git replay topic1..topic2 >result ' +test_expect_success 'using replay to also rebase a contained branch' ' + git replay --contained --onto main main..topic3 >result && + + test_line_count = 2 result && + cut -f 3 -d " " result >new-branch-tips && + + git log --format=%s $(head -n 1 new-branch-tips) >actual && + test_write_lines F C M L B A >expect && + test_cmp expect actual && + + git log --format=%s $(tail -n 1 new-branch-tips) >actual && + test_write_lines H G F C M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/topic1 " >expect && + printf "%s " $(head -n 1 new-branch-tips) >>expect && + git rev-parse topic1 >>expect && + printf "update refs/heads/topic3 " >>expect && + printf "%s " $(tail -n 1 new-branch-tips) >>expect && + git rev-parse topic3 >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to also rebase a contained branch' ' + git -C bare replay --contained --onto main main..topic3 >result-bare && + test_cmp expect result-bare +' + test_done From patchwork Wed Nov 15 14:33:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Couder X-Patchwork-Id: 13456840 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C8BA33CC7 for ; Wed, 15 Nov 2023 14:34:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mpCvSZzv" Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E359418E for ; Wed, 15 Nov 2023 06:34:07 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-40a5a444c3eso17610415e9.2 for ; Wed, 15 Nov 2023 06:34:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700058846; x=1700663646; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HdYvPF40PLW9J9JPPdsPaTxSDxkzVO+P/vd76mIXd+o=; b=mpCvSZzvsO/fjqs5Vke8nXeu7TNdUIdQ47g3VMeu8c9W4X3crw1G2leRzyFj4dC9qM qtZ8MAmaRv3GLOCyW1vfPapaOPdiXkSjfLWd4Itl0q4XBYywXMCUTsAF5maCbdSpVrKA LrVhHLTKGkVmGTfT+6+PDBfsCL5j6ShPOAQyJZpqWjENJXnodJ0KXj1ZNg+FcJl78TWw vfAi0vbAJd3KEBN3fc9Q39bHsFzF2vYFwRnrdeeoWUqUaJSqH53F6oBeUxV5ZsD/ijun PNvrgBcvS8VUvcaicmfMm8VraD0isMt9r1mVrFBsqugXEywjrj8AcNky/0iB1gAOZ2UO C2mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700058846; x=1700663646; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HdYvPF40PLW9J9JPPdsPaTxSDxkzVO+P/vd76mIXd+o=; b=CWAeR+JjekkxlVMaKgoWZY3mGCKx+8Owvhj3iSD+ap6JsUt6KNLDzEVR7xwIwjWWwi 3T9XAJaQPi1E4oR31+R5KLRGaNg1BqXiEMG1PBtOTwtU33arrDyI0EY+fkDA7zv7XIhI zZ69fACV/xOQmlBmwFQmsKWOEttgeAaVH0G0+vamAiNqLBZP18gaNp/fhFoBPypN4dOJ OT4O0yNRLmOCWuHWp0gU5V9+mwIIAcVq1giahrsMN415yrUy+TSgj2JORTJaI5UDkC3i IKMYEZMgejgYYtZZal2sd6TKfu3s4dx6hl4ScrUYu2DdfvULt/iB7//lJ6/rKfifOnDi jNYQ== X-Gm-Message-State: AOJu0YzXafAItaw1w5r+kdh9D3d+sIfLXmzROrpeLzqQ55b8Yf8d1i/a TGTvYttaaixXPmtBh6miSZ385RbHVLM= X-Google-Smtp-Source: AGHT+IHkDpTGDyIlHzqcraJgBy33nL/DY39TnTkUKonucceE+4o2vElpbRoIdwuXpSnYuqjIER8qew== X-Received: by 2002:a05:600c:511d:b0:403:272:4414 with SMTP id o29-20020a05600c511d00b0040302724414mr11930992wms.0.1700058845804; Wed, 15 Nov 2023 06:34:05 -0800 (PST) Received: from localhost.localdomain ([2001:861:3f04:7ca0:a40b:e654:dd4c:2f5f]) by smtp.gmail.com with ESMTPSA id q15-20020a05600c46cf00b004060f0a0fd5sm15207643wmo.13.2023.11.15.06.34.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 06:34:05 -0800 (PST) From: Christian Couder To: git@vger.kernel.org Cc: Junio C Hamano , Patrick Steinhardt , Johannes Schindelin , Elijah Newren , John Cai , Derrick Stolee , Phillip Wood , Calvin Wan , Toon Claes , Dragan Simic , Linus Arver , Christian Couder Subject: [PATCH v7 14/14] replay: stop assuming replayed branches do not diverge Date: Wed, 15 Nov 2023 15:33:27 +0100 Message-ID: <20231115143327.2441397-15-christian.couder@gmail.com> X-Mailer: git-send-email 2.43.0.rc1.15.g29556bcc86 In-Reply-To: <20231115143327.2441397-1-christian.couder@gmail.com> References: <20231102135151.843758-1-christian.couder@gmail.com> <20231115143327.2441397-1-christian.couder@gmail.com> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Elijah Newren The replay command is able to replay multiple branches but when some of them are based on other replayed branches, their commit should be replayed onto already replayed commits. For this purpose, let's store the replayed commit and its original commit in a key value store, so that we can easily find and reuse a replayed commit instead of the original one. Co-authored-by: Christian Couder Signed-off-by: Elijah Newren Signed-off-by: Christian Couder --- builtin/replay.c | 44 ++++++++++++++++++++++++++-------- t/t3650-replay-basics.sh | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/builtin/replay.c b/builtin/replay.c index e14e33bcc5..f37e511d8e 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -223,20 +223,33 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, strset_clear(&rinfo.positive_refs); } +static struct commit *mapped_commit(kh_oid_map_t *replayed_commits, + struct commit *commit, + struct commit *fallback) +{ + khint_t pos = kh_get_oid_map(replayed_commits, commit->object.oid); + if (pos == kh_end(replayed_commits)) + return fallback; + return kh_value(replayed_commits, pos); +} + static struct commit *pick_regular_commit(struct commit *pickme, - struct commit *last_commit, + kh_oid_map_t *replayed_commits, + struct commit *onto, struct merge_options *merge_opt, struct merge_result *result) { - struct commit *base; + struct commit *base, *replayed_base; struct tree *pickme_tree, *base_tree; base = pickme->parents->item; + replayed_base = mapped_commit(replayed_commits, base, onto); + result->tree = repo_get_commit_tree(the_repository, replayed_base); pickme_tree = repo_get_commit_tree(the_repository, pickme); base_tree = repo_get_commit_tree(the_repository, base); - merge_opt->branch1 = short_commit_name(last_commit); + merge_opt->branch1 = short_commit_name(replayed_base); merge_opt->branch2 = short_commit_name(pickme); merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2); @@ -250,7 +263,7 @@ static struct commit *pick_regular_commit(struct commit *pickme, merge_opt->ancestor = NULL; if (!result->clean) return NULL; - return create_commit(result->tree, pickme, last_commit); + return create_commit(result->tree, pickme, replayed_base); } int cmd_replay(int argc, const char **argv, const char *prefix) @@ -266,6 +279,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) struct merge_options merge_opt; struct merge_result result; struct strset *update_refs = NULL; + kh_oid_map_t *replayed_commits; int ret = 0; const char * const replay_usage[] = { @@ -362,21 +376,30 @@ int cmd_replay(int argc, const char **argv, const char *prefix) init_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; - - result.tree = repo_get_commit_tree(the_repository, onto); last_commit = onto; + replayed_commits = kh_init_oid_map(); while ((commit = get_revision(&revs))) { const struct name_decoration *decoration; + khint_t pos; + int hr; if (!commit->parents) die(_("replaying down to root commit is not supported yet!")); if (commit->parents->next) die(_("replaying merge commits is not supported yet!")); - last_commit = pick_regular_commit(commit, last_commit, &merge_opt, &result); + last_commit = pick_regular_commit(commit, replayed_commits, onto, + &merge_opt, &result); if (!last_commit) break; + /* Record commit -> last_commit mapping */ + pos = kh_put_oid_map(replayed_commits, commit->object.oid, &hr); + if (hr == 0) + BUG("Duplicate rewritten commit: %s\n", + oid_to_hex(&commit->object.oid)); + kh_value(replayed_commits, pos) = last_commit; + /* Update any necessary branches */ if (advance_name) continue; @@ -405,13 +428,14 @@ int cmd_replay(int argc, const char **argv, const char *prefix) } merge_finalize(&merge_opt, &result); - ret = result.clean; - -cleanup: + kh_destroy_oid_map(replayed_commits); if (update_refs) { strset_clear(update_refs); free(update_refs); } + ret = result.clean; + +cleanup: release_revisions(&revs); /* Return */ diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index d6286f9580..389670262e 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -143,4 +143,56 @@ test_expect_success 'using replay on bare repo to also rebase a contained branch test_cmp expect result-bare ' +test_expect_success 'using replay to rebase multiple divergent branches' ' + git replay --onto main ^topic1 topic2 topic4 >result && + + test_line_count = 2 result && + cut -f 3 -d " " result >new-branch-tips && + + git log --format=%s $(head -n 1 new-branch-tips) >actual && + test_write_lines E D M L B A >expect && + test_cmp expect actual && + + git log --format=%s $(tail -n 1 new-branch-tips) >actual && + test_write_lines J I M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/topic2 " >expect && + printf "%s " $(head -n 1 new-branch-tips) >>expect && + git rev-parse topic2 >>expect && + printf "update refs/heads/topic4 " >>expect && + printf "%s " $(tail -n 1 new-branch-tips) >>expect && + git rev-parse topic4 >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to rebase multiple divergent branches, including contained ones' ' + git -C bare replay --contained --onto main ^main topic2 topic3 topic4 >result && + + test_line_count = 4 result && + cut -f 3 -d " " result >new-branch-tips && + + >expect && + for i in 2 1 3 4 + do + printf "update refs/heads/topic$i " >>expect && + printf "%s " $(grep topic$i result | cut -f 3 -d " ") >>expect && + git -C bare rev-parse topic$i >>expect || return 1 + done && + + test_cmp expect result && + + test_write_lines F C M L B A >expect1 && + test_write_lines E D C M L B A >expect2 && + test_write_lines H G F C M L B A >expect3 && + test_write_lines J I M L B A >expect4 && + + for i in 1 2 3 4 + do + git -C bare log --format=%s $(grep topic$i result | cut -f 3 -d " ") >actual && + test_cmp expect$i actual || return 1 + done +' + test_done