aboutsummaryrefslogtreecommitdiffstats
path: root/builtin/replay.c
AgeCommit message (Collapse)AuthorFilesLines
10 daysMerge branch 'en/replay-doc-revision-range'Junio C Hamano1-1/+1
The use of "revision" (a connected set of commits) has been clarified in the "git replay" documentation. * en/replay-doc-revision-range: Documentation/git-replay.adoc: fix errors around revision range
10 daysMerge branch 'pw/replay-exclude-gpgsig-fix'Junio C Hamano1-1/+1
"git replay" forgot to omit the "gpgsig-sha256" extended header from the resulting commit the same way it omits "gpgsig", which has been corrected. * pw/replay-exclude-gpgsig-fix: replay: do not copy "gpgsign-sha256" header
2025-11-28Documentation/git-replay.adoc: fix errors around revision rangeElijah Newren1-1/+1
There was significant confusion in the git-replay manual about what constitutes a revision range. As noted in f302c1e4aa09 (revisions(7): clarify that most commands take a single revision range, 2021-05-18): Commands that are specifically designed to take two distinct ranges (e.g. "git range-diff R1 R2" to compare two ranges) do exist, but they are exceptions. Unless otherwise noted, all "git" commands that operate on a set of commits work on a single revision range. `git replay` is not an exception, but a few places in the manual were written as though it were. These appear to have come in revisions to the original series, between v3->v4 (see https://lore.kernel.org/git/CAP8UFD3bpLrVW97DH7j=V9H2GsTSAkksC9L3QujQERFk_kLnZA@mail.gmail.com/ , "More than one <revision-range> can be passed") and between v6->v7 (https://lore.kernel.org/git/20231115143327.2441397-1-christian.couder@gmail.com/, "Takes ranges of commits"), and I missed both of these revisions when reviewing. Fix them now. There was also a reference to the "Commit Limiting options below", but this page has no such section of options; strike the misleading reference. It is worth noting that we are documenting existing behavior, rather than optimal behavior. Junio has multiple times suggested introducing alternative ways to walk revisions and use them in `git replay --advance`, e.g. at * https://lore.kernel.org/git/xmqqy1mqo6kv.fsf@gitster.g/ * https://lore.kernel.org/git/xmqq8rb3is8c.fsf@gitster.g/ * https://lore.kernel.org/git/xmqqtsydj2zk.fsf@gitster.g/ (item (2)) If/when we introduce some new revision walking flag that implements one of these alternate types of revision walks, we can update the --advance option and this manual appropriately. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-26replay: do not copy "gpgsign-sha256" headerPhillip Wood1-1/+1
When "git replay" replays a commit it copies the extended headers across from the original commit. However, if the original commit was signed, we do not want to copy the header associated with the signature is it wont be valid for the new commit. The code already knows to avoid coping the "gpgsig" header but does not know to avoid copying the "gpgsig-sha256" header. Add that header to the list of exclusions to match what "git commit --amend" does. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-05replay: add replay.refAction config optionSiddharth Asthana1-4/+20
Add a configuration variable to control the default behavior of git replay for updating references. This allows users who prefer the traditional pipeline output to set it once in their config instead of passing --ref-action=print with every command. The config variable uses string values that mirror the behavior modes: * replay.refAction = update (default): atomic ref updates * replay.refAction = print: output commands for pipeline Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Elijah Newren <newren@gmail.com> Helped-by: Christian Couder <christian.couder@gmail.com> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-05replay: make atomic ref updates the default behaviorSiddharth Asthana1-10/+101
The git replay command currently outputs update commands that can be piped to update-ref to achieve a rebase, e.g. git replay --onto main topic1..topic2 | git update-ref --stdin This separation had advantages for three special cases: * it made testing easy (when state isn't modified from one step to the next, you don't need to make temporary branches or have undo commands, or try to track the changes) * it provided a natural can-it-rebase-cleanly (and what would it rebase to) capability without automatically updating refs, similar to a --dry-run * it provided a natural low-level tool for the suite of hash-object, mktree, commit-tree, mktag, merge-tree, and update-ref, allowing users to have another building block for experimentation and making new tools However, it should be noted that all three of these are somewhat special cases; users, whether on the client or server side, would almost certainly find it more ergonomic to simply have the updating of refs be the default. For server-side operations in particular, the pipeline architecture creates process coordination overhead. Server implementations that need to perform rebases atomically must maintain additional code to: 1. Spawn and manage a pipeline between git-replay and git-update-ref 2. Coordinate stdout/stderr streams across the pipe boundary 3. Handle partial failure states if the pipeline breaks mid-execution 4. Parse and validate the update-ref command output Change the default behavior to update refs directly, and atomically (at least to the extent supported by the refs backend in use). This eliminates the process coordination overhead for the common case. For users needing the traditional pipeline workflow, add a new --ref-action=<mode> option that preserves the original behavior: git replay --ref-action=print --onto main topic1..topic2 | git update-ref --stdin The mode can be: * update (default): Update refs directly using an atomic transaction * print: Output update-ref commands for pipeline use Test suite changes: All existing tests that expected command output now use --ref-action=print to preserve their original behavior. This keeps the tests valid while allowing them to verify that the pipeline workflow still works correctly. New tests were added to verify: - Default atomic behavior (no output, refs updated directly) - Bare repository support (server-side use case) - Equivalence between traditional pipeline and atomic updates - Real atomicity using a lock file to verify all-or-nothing guarantee - Test isolation using test_when_finished to clean up state - Reflog messages include replay mode and target A following commit will add a replay.refAction configuration option for users who prefer the traditional pipeline output as their default behavior. Helped-by: Elijah Newren <newren@gmail.com> Helped-by: Patrick Steinhardt <ps@pks.im> Helped-by: Christian Couder <christian.couder@gmail.com> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-05replay: use die_for_incompatible_opt2() for option validationSiddharth Asthana1-3/+3
In preparation for adding the --ref-action option, convert option validation to use die_for_incompatible_opt2(). This helper provides standardized error messages for mutually exclusive options. The following commit introduces --ref-action which will be incompatible with certain other options. Using die_for_incompatible_opt2() now means that commit can cleanly add its validation using the same pattern, keeping the validation logic consistent and maintainable. This also aligns git-replay's option handling with how other Git commands manage option conflicts, using the established die_for_incompatible_opt*() helper family. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-06-05repo_logmsg_reencode: fix memory leak when use repo_logmsg_reencode ()Lidong Yan1-0/+1
pretty.c:repo_logmsg_reencode() allocated memory should be freed with repo_unuse_commit_buffer(). Callers sometimes forgot free it at exit point. Add `repo_unuse_commit_buffer()` in insert_records_from_trailers at builtin/shortlog.c and create_commit at builtin/replay.c Signed-off-by: Lidong Yan <502024330056@smail.nju.edu.cn> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-05-14replay: replace the_repository with repo parameter passed to cmd_replay ()Elijah Newren1-30/+35
Replace the_repository everywhere with repo, feed repo from cmd_replay() to all the other functions in the file that need it, and remove the UNUSED annotation on repo. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-06parse-options: introduce die_for_incompatible_opt2()Toon Claes1-3/+4
The functions die_for_incompatible_opt3() and die_for_incompatible_opt4() already exist to die whenever a user specifies three or four options respectively that are not compatible. Introduce die_for_incompatible_opt2() which dies when two options that are incompatible are set. Signed-off-by: Toon Claes <toon@iotcl.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-12-06global: mark code units that generate warnings with `-Wsign-compare`Patrick Steinhardt1-1/+3
Mark code units that generate warnings with `-Wsign-compare`. This allows for a structured approach to get rid of all such warnings over time in a way that can be easily measured. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-09-13builtin: remove USE_THE_REPOSITORY_VARIABLE from builtin.hJohn Cai1-0/+1
Instead of including USE_THE_REPOSITORY_VARIABLE by default on every builtin, remove it from builtin.h and add it to all the builtins that include builtin.h (by definition, that means all builtins/*.c). Also, remove the include statement for repository.h since it gets brought in through builtin.h. The next step will be to migrate each builtin from having to use the_repository. Signed-off-by: John Cai <johncai86@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-09-13builtin: add a repository parameter for builtin functionsJohn Cai1-1/+4
In order to reduce the usage of the global the_repository, add a parameter to builtin functions that will get passed a repository variable. This commit uses UNUSED on most of the builtin functions, as subsequent commits will modify the actual builtins to pass the repository parameter down. Signed-off-by: John Cai <johncai86@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-08-14Merge branch 'ps/leakfixes-part-3'Junio C Hamano1-6/+14
More leakfixes. * ps/leakfixes-part-3: (24 commits) commit-reach: fix trivial memory leak when computing reachability convert: fix leaking config strings entry: fix leaking pathnames during delayed checkout object-name: fix leaking commit list items t/test-repository: fix leaking repository builtin/credential-cache: fix trivial leaks builtin/worktree: fix leaking derived branch names builtin/shortlog: fix various trivial memory leaks builtin/rerere: fix various trivial memory leaks builtin/credential-store: fix leaking credential builtin/show-branch: fix several memory leaks builtin/rev-parse: fix memory leak with `--parseopt` builtin/stash: fix various trivial memory leaks builtin/remote: fix various trivial memory leaks builtin/remote: fix leaking strings in `branch_list` builtin/ls-remote: fix leaking `pattern` strings builtin/submodule--helper: fix leaking buffer in `is_tip_reachable` builtin/submodule--helper: fix leaking clone depth parameter builtin/name-rev: fix various trivial memory leaks builtin/describe: fix trivial memory leak when describing blob ...
2024-08-01builtin/replay: plug leaking `advance_name` variablePatrick Steinhardt1-6/+14
The `advance_name` variable can either contain a static string when parsed via the `--advance` command line option or it may be an allocated string when set via `determine_replay_mode()`. Because we cannot be sure whether it is allocated or not we just didn't free it at all, resulting in a memory leak. Split up the variables such that we can track the static and allocated strings separately and then free the allocated one to fix the memory leak. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-07-13merge-recursive: honor diff.algorithmAntonin Delpeuch1-1/+1
The documentation claims that "recursive defaults to the diff.algorithm config setting", but this is currently not the case. This fixes it, ensuring that diff.algorithm is used when -Xdiff-algorithm is not supplied. This affects the following porcelain commands: "merge", "rebase", "cherry-pick", "pull", "stash", "log", "am" and "checkout". It also affects the "merge-tree" ancillary interrogator. This change refactors the initialization of merge options to introduce two functions, "init_merge_ui_options" and "init_merge_basic_options" instead of just one "init_merge_options". This design follows the approach used in diff.c, providing initialization methods for porcelain and plumbing commands respectively. Thanks to that, the "replay" and "merge-recursive" plumbing commands remain unaffected by diff.algorithm. Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-06-11commit: fix leaking parents when calling `commit_tree_extended()`Patrick Steinhardt1-5/+9
When creating commits via `commit_tree_extended()`, the caller passes in a string list of parents. This call implicitly transfers ownership of that list to the function, which is quite surprising to begin with. But to make matters worse, `commit_tree_extended()` doesn't even bother to free the list of parents in error cases. The result is a memory leak, and one that the caller cannot fix by themselves because they do not know whether parts of the string list have already been released. Refactor the code such that callers can keep ownership of the list of parents, which is getting indicated by parameter being a constant pointer now. Free the lists at the calling site and add a common exit path to those sites as required. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-04-18builtin: stop using `the_index`Patrick Steinhardt1-1/+0
Convert builtins to use `the_repository->index` instead of `the_index`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: stop assuming replayed branches do not divergeElijah Newren1-10/+34
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: add --contained to rebase contained branchesElijah Newren1-2/+12
Let's add a `--contained` option that can be used along with `--onto` to rebase all the branches contained in the <revision-range> argument. Co-authored-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: add --advance or 'cherry-pick' modeElijah Newren1-9/+176
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: use standard revision rangesElijah Newren1-17/+4
Instead of the fixed "<oldbase> <branch>" arguments, the replay command now accepts "<revision-range>..." 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 <dsimic@manjaro.org> Helped-by: Linus Arver <linusa@google.com> Co-authored-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: make it a minimal server side commandElijah Newren1-52/+26
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: remove HEAD related sanity checkElijah Newren1-7/+1
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: remove progress and info outputElijah Newren1-6/+1
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: add an important FIXME comment about gpg signingElijah Newren1-1/+1
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: change rev walking optionsElijah Newren1-7/+41
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 <Johannes.Schindelin@gmx.de> Co-authored-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: introduce pick_regular_commit()Elijah Newren1-20/+34
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: die() instead of failing assert()Elijah Newren1-1/+6
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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: start using parse_options APIElijah Newren1-13/+32
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 "<oldbase> <branch>" 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 <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-11-26replay: introduce new builtinElijah Newren1-0/+223
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 <Johannes.Schindelin@gmx.de> Co-authored-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>