summaryrefslogtreecommitdiff
path: root/sequencer.c
AgeCommit message (Collapse)AuthorFilesLines
7 daysMerge branch 'hn/checkout-m-autostash-refine' into nextJunio C Hamano1-39/+70
The autostash fallback in 'git checkout -m' has been refined to only retry when there are local changes. Additionally, a blank line now visually separates autostash conflict advice from the subsequent branch-switch message. * hn/checkout-m-autostash-refine: checkout: separate autostash conflict advice from branch-switch message stash: reserve exit status 1 for conflicts
7 daysMerge branch 'en/no-amend-during-conflicts' into nextJunio C Hamano1-1/+58
Teach 'am', 'revert', and 'rebase' that running 'commit --amend' or a partial 'commit <paths>' makes no sense during operations that stop and return control to the user to resolve conflicts left in the working tree, just like 'cherry-pick' and 'merge' do. * en/no-amend-during-conflicts: commit: refuse partial commits during conflict resolution commit: refuse to amend during conflict resolution commit: reword the empty-commit rebase amend error commit: allow a partial commit when a rebase pick becomes empty commit: clarify FROM_REBASE_PICK and is_from_rebase() names
11 daysstash: reserve exit status 1 for conflictsHarald Nordgren1-39/+70
"git stash apply", "pop" and "branch" exit with status 1 both when applying the stash entry resulted in conflicts and when they fail for other reasons, so callers cannot tell the two apart. Follow the convention of "git merge-tree" and the merge strategies, which exit with status 1 to indicate conflicts and with a different non-zero status for errors: those subcommands now exit with status 1 only when applying the stash entry resulted in conflicts, in which case the stash entry is left in place, and exit with status 128, the status die() uses, when they fail for other reasons. Document the exit statuses. The only subcommand implementations that can return a positive value are "apply", "pop" and "branch", which return the value of do_apply_stash(): "apply" returns it directly, and "pop" and "branch" drop the stash entry, via do_drop_stash(), which always returns 0, only when the application succeeded. do_apply_stash() only returns a positive value when the three-way merge was unclean. cmd_stash() now maps negative values to 128 and passes positive values through as the exit status, so exit status 1 unambiguously indicates conflicts. enum stash_apply_result makes the convention explicit, and the autostash helpers use it to tell users that their stashed changes were saved when applying them fails. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 dayscommit: refuse to amend during conflict resolutionElijah Newren1-0/+57
Running `git commit --amend` during conflict resolution is an ugly foot-gun. For many years, we have rejected amending during conflict resolution in the middle of - a merge - a cherry-pick However, this was never extended to other operations that can also produce conflicts: - an `am` operation - a revert - a rebase Extend it to handle these other cases now. Extending to `am`, revert, and the apply backend of rebase are fairly straightforward. However, with the merge backend of rebase we have to be more careful, since it powers interactive rebases and - the interactive machinery internally uses `git commit --amend` for `squash` and `reword` directives - users are expected to `git commit --amend` after hitting an `edit` or `break` directive So, we need to be careful with rebase to only reject amending when doing conflict resolution. A few files under the rebase-merge/ directory provide us the necessary information: - stopped-sha is written only when the rebase stops and hands control back to the user, so its presence marks a genuine stop -- as opposed to the sequencer's own internal `git commit --amend` while applying a squash, fixup, or reword, during which no stopped-sha exists. - amend is written only when the rebase stops with HEAD already pointing at the commit the user is meant to amend: a clean `edit`, or a fast-forward `reword`. Its absence at a stop therefore means the commit did not apply, so HEAD is the previously-applied commit rather than the one being rebased -- exactly the case we refuse. So for the merge backend we die when stopped-sha exists and amend does not. This covers a plain conflicted pick as well as a conflicted `edit` (both leave HEAD on the previously-applied commit), while still allowing a clean `edit` or `reword` stop and a `break` stop (no stopped-sha). stopped-sha is unlinked at the start of the resume loop, so a resumed squash's internal amend is unaffected. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 dayscommit: clarify FROM_REBASE_PICK and is_from_rebase() namesElijah Newren1-1/+1
Commit 430b75f7209c (commit: give correct advice for empty commit during a rebase, 2019-12-06) introduced a FROM_REBASE_PICK enum value and an is_from_rebase() function. Those names failed to convey that they were specifically about hitting a commit that becomes empty when rebasing. Clarify their names now. While at it, change `whence == FROM_REBASE_NOW_EMPTY` to use `is_from_rebase_now_empty(whence)`. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-17Merge branch 'en/sequencer-lose-pretty-given' into nextJunio C Hamano1-1/+0
The setting of a now-unused member '.pretty_given' in the sequencer machinery has been removed. * en/sequencer-lose-pretty-given: sequencer: remove unnecessary variable setting
2026-08-12sequencer: release the ODB before spawning git commitJohannes Schindelin1-0/+1
As of 4557f1add261 (rebase--helper: add a builtin helper for interactive rebases, 2017-02-09), continuing an interactive rebase uses the builtin sequencer, which spawns `git commit`. The child may trigger auto-maintenance, which may need to replace files for which the sequencer still holds resources. See https://github.com/git-for-windows/git/issues/6315: on Windows, this produces unlink retry prompts that cannot succeed while the sequencer waits for the child. Resources such as file handles or memory mappings must be released before spawning a command that may run auto-maintenance, as established by 28d04e1ec197 (run-command: offer to close the object store before running, 2021-09-09): release the ODB file handles and memory mappings, so that auto-gc can repack (potentially deleting existing packfiles in the process); If the sequencer needs to access the ODB afterwards, it will gracefully (re-)open the ODB. Release the sequencer's ODB before spawning `git commit`. The regression test uses the legacy-delete trick introduced by 69ed0e35a754 (mingw: optionally use legacy (non-POSIX) delete semantics, 2026-05-07) to trigger the failure on modern Windows. Assisted-by: GPT-5.6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12sequencer: remove unnecessary variable settingElijah Newren1-1/+0
revs.pretty_given is only ever read in builtin/log.c, and nothing from builtin/log.c is ever called from sequencer.c. So setting this variable cannot do anything. This was introduced in commit 62db524779 ("rebase -i: generate the script via rebase--helper", 2017-07-14), which used `git rev-list` even though its commit message describes the logic as having been based on `git log`. Because of this, I am guessing this line was copied or ported from part of builtin/log.c without recognizing that this line was not doing anything and could be removed. It's certainly not doing anything now, though, so remove it. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05Merge branch 'pw/rebase-fixup-fixes'Junio C Hamano1-5/+26
Two bugs in how 'git rebase' handles skipped 'fixup' and 'squash' commands have been fixed. One bug caused an incorrect commit count to be shown in the template message when multiple commands were skipped, and another prevented the editor from opening when the final command in a chain containing 'fixup -c' was skipped. * pw/rebase-fixup-fixes: rebase: remember fixup -c after skipping fixup/squash rebase -i: fix counting of fixups after rebase --skip
2026-07-27Merge branch 'pw/rebase-drop-notes-with-commit'Junio C Hamano1-32/+92
The rebase post-rewrite notes-copying logic has been corrected. When a commit is dropped during rebase (e.g., because its changes are already upstream), it is no longer recorded as rewritten, preventing its notes from being copied to an unrelated commit. * pw/rebase-drop-notes-with-commit: sequencer: do not record dropped commits as rewritten sequencer: use an enum to represent result of picking a commit sequencer: simplify pick_one_commit() sequencer: remove unnecessary condition in pick_one_commit() sequencer: simplify handling of fixup with conflicts sequencer: remove unnecessary "or" in pick_one_commit() sequencer: never reschedule on failed commit sequencer: be more careful with external merge t3400: restore coverage for note copying with apply backend
2026-07-26rebase: remember fixup -c after skipping fixup/squashPhillip Wood1-4/+16
When the final command in a chain of "fixup" and "squash" commands is skipped, we should prompt the user to edit the commit message if the chain contains a "fixup -c" command that was not skipped. Unfortunately, commit_staged_changes() only looks for completed "squash" commands and so does not prompt the user to edit the message. Fix this by recording whether a fixup command has the "-c" flag set and then checking whether we have seen either a "fixup -c" or a "squash" command. Add regression tests for skipping a command in the middle of the chain (which currently works but has no test coverage), and for skipping the final command (which is fixed by this patch). Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-26rebase -i: fix counting of fixups after rebase --skipPhillip Wood1-1/+10
When the sequencer processes a chain of "fixup" and "squash" commands it keeps a list of the commands that have been executed. If there are conflicts, then the list is saved when the rebase stops for the user to resolve them. When the rebase resumes, the list is loaded and is used to initialize the count of how many "fixup" and "squash" commands have been processed; if a command has been skipped with "git rebase --skip", then the last command needs to be popped off the end of the list. To count the number of commands, commit_staged_changes() uses the number of newlines in the file plus one. This is due to the slightly unusual way the list is constructed - instead of appending a newline when a command is added, a newline is inserted before the command if the current count is greater than zero. Therefore, when we pop a skipped command off the list, we should also remove the newline that precedes it. Otherwise, when a new command is added, a blank line will be left before it, which will contribute to the fixup count the next time the file is read. Unfortunately, the preceding newline is not removed, leading to an incorrect count. Fix this by removing the newline that appears before the skipped command. In addition to fixing the code that removes a skipped command from the list, the code that reads the list is fixed to skip blank lines. We have had reports of users starting a rebase with one version of git and continuing it with another. Often this happens because the version of git bundled with an IDE or TUI differs from the one used at the command line. By fixing both the reading and writing ends of the problem we ensure the count is correct when an older version of git reads the fixup file written by a newer version and vice versa. Triggering the incorrect count requires the user to skip two "fixup" or "squash" commands before the final command in the chain. An existing test is extended to prevent future regressions. The consequence of miscounting is not serious: we just print the wrong count in the header of the commit message template. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-16copy: drop dependency on `the_repository`Patrick Steinhardt1-3/+3
When copying a file we need to potentially adapt permissions of the new file based on whether or not "core.shared" is enabled. Parsing this configuration makes us implicitly depend on `the_repository`. Refactor the code to instead require the caller to pass in a repository so that we can remove `USE_THE_REPOSITORY_VARIABLE`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15Merge branch 'ps/history-drop'Junio C Hamano1-6/+11
The experimental 'git history' command has been taught a new 'drop' subcommand to remove a commit, with its descendants replayed onto its parent. * ps/history-drop: builtin/history: implement "drop" subcommand builtin/history: split handling of ref updates into two phases replay: expose `replay_result_queue_update()` reset: stop assuming that the caller passes in a clean index reset: allow the caller to specify the current HEAD object reset: introduce ability to skip updating HEAD reset: introduce dry-run mode reset: modernize flags passed to `reset_working_tree()` reset: rename `reset_head()` reset: drop `USE_THE_REPOSITORY_VARIABLE` read-cache: split out function to drop unmerged entries to stage 0
2026-07-15sequencer: do not record dropped commits as rewrittenPhillip Wood1-5/+19
If a commit gets dropped because its changes are already upstream then we should not record it as rewritten. As well as confusing any post-rewrite hooks, it means we end up copying the notes from the dropped commit to the commit that was picked immediately before the one that was dropped. While we do not want to record the dropped commit as rewritten, if it is the final commit in a chain of fixups then we need to flush the list of rewritten commits. The behavior of an "edit" command where the commit is dropped is changed so that "rebase --continue" will not amend the previous pick. However, as the code comment notes it will still be erroneously recorded as rewritten when the rebase continues. That will need to be addressed separately along with not recording skipped commits as rewritten. The initialization of "drop_commit" is moved to ensure it is initialized when rewording a fast-forwarded commit. Reported-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Tested-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: use an enum to represent result of picking a commitPhillip Wood1-16/+45
Rather than using an integer where -1 is an error, 0 is success and 1 indicates there were conflicts, use an enum. This is clearer and lets us add a separate return value for commits that are dropped because they become empty in the next commit. Note we continue to use "return error(...)" to return errors and take advantage of C's lax typing of enums Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: simplify pick_one_commit()Phillip Wood1-8/+11
Unless we're rebasing, all we do in pick_one_commit() is call do_pick_commit() and return its result. Simplify the code by returning early if we're not rebasing so that we don't have to repeatedly call is_rebase_i() in the rest of the function. Note that there are a couple of conditions that do not call is_rebase_i() but they check for either an "edit" or a "fixup" command, both of which imply we're rebasing. The only block that does not return early is the one guarded by "!res". Move the return into that block to make it clear that after recording the commit as rewritten, all we do is return from the function. As the conditional blocks are all mutually exclusive (either the conditions are mutually exclusive, or an earlier conditional block that would match a later one contains a "return" statement) chain them together with "else if" to make that clear. While we could remove "res" from the conditions below "if (!res)" they are left alone because, when we start using an enum in the next commit, it makes it clear that these clauses are handling cases where there are conflicts. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: remove unnecessary condition in pick_one_commit()Phillip Wood1-1/+1
item->commit holds the commit to be picked and so it must be non-NULL otherwise pick_one_commit() would not know which commit to pick. It is also unconditionally dereferenced in do_pick_commit() which is called at the top of this function. Therefore the check to see if it is non-NULL is superfluous. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: simplify handling of fixup with conflictsPhillip Wood1-3/+1
Commit e032abd5a0 (rebase: fix rewritten list for failed pick, 2023-09-06) introduced an early return when res == -1, so if we enter this conditional block then res is positive. After the last couple of commits the only possible positive value is 1. That means we can simplify the code by removing the conditional call to intend_to_amend() and have error_failed_squash() request that it is called in error_with_patch() instead. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: remove unnecessary "or" in pick_one_commit()Phillip Wood1-3/+2
If error_with_patch(..., res, ...) succeeds then it returns "res", if it fails then it returns -1. This means that or-ing the return value with "res" is pointless as the result is the same as the return value. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: never reschedule on failed commitPhillip Wood1-0/+6
If "git commit" fails to run then run_git_commit() returns -1 which causes the current command to be rescheduled. This is incorrect as we have successfully picked the commit and have written all the state files we need to successfully commit when the user continues. Fix this by converting -1 to 1 which matches what do_merge() does. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15sequencer: be more careful with external mergePhillip Wood1-4/+15
If an external merge strategy cannot merge (for example because it would overwrite an untracked file) it exits with a non-zero exit code other than 1. This should be treated differently from a merge with conflicts, which is signaled by an exit code of 1, because, as the merge failed, we need to reschedule the last pick. The caller expects us to return -1 in this case. Also reschedule without trying to merge if the commit message cannot be written as that prevents us from successfully picking the commit. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06Merge branch 'pw/status-rebase-todo'Junio C Hamano1-12/+27
The display of the rebase todo list in "git status" has been improved to correctly abbreviate object IDs for more commands and avoid misinterpreting refs as object IDs. * pw/status-rebase-todo: status: improve rebase todo list parsing sequencer: factor out parsing of todo commands
2026-07-03reset: introduce ability to skip updating HEADPatrick Steinhardt1-1/+3
In a subsequent commit we'll introduce a new caller to `reset_working_tree()` that really only wants to update the index and working tree, without updating any references. Introduce a new flag that makes the caller opt in to updating HEAD and adapt all callers to set that flag. Note that in a previous iteration we instead introduced a flag that made callers opt out of updating any references. This was somewhat awkward though because we already have the `UPDATE_ORIG_HEAD` flag, so the result was somewhat inconsistent. Suggested-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> [jc: fixed-up a typo pointed out by Christian] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-01reset: modernize flags passed to `reset_working_tree()`Patrick Steinhardt1-3/+6
The flags passed to `reset_working_tree()` are declared as defines. This has fallen a bit out of practice nowadays, where we instead prefer to use enums. Furthermore, the prefix of those flags does not match the function name anymore after the rename in the preceding commit. Adapt the code to follow modern best practices and adapt the flag names. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-01reset: rename `reset_head()`Patrick Steinhardt1-4/+4
In a subsequent commit we're about to adapt `reset_head()` so that the reference update to HEAD is optional, only. At this point the function starts to feel misnamed, as it doesn't necessarily have anything to do with the HEAD reference anymore. The gist of the function then is that we reset the working tree to a specific new commit, updating both the index and the checked-out files. Rename it to `reset_working_tree()` to better reflect that. Note that we don't adjust the flags yet. This will happen in a subsequent commit. Suggested-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-23sequencer: factor out parsing of todo commandsPhillip Wood1-12/+27
Move the code that parses todo commands into a separate function so that it can be shared with "git status" in the next commit. As we know the input is NUL terminated we do not pass a pointer to the end of the line and instead test for a blank line by looking for NUL, CR LF, or LF. We use starts_with() instead of starts_with_mem() for the same reason. This results in slightly different behavior when there a CR at the start of the line that is not followed by LF. Previously such a line was treated as a comment rather than an invalid line. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-09Merge branch 'rs/strbuf-add-oid-hex'Junio C Hamano1-2/+2
Formatting object name in full hexadecimal form has been optimized by using a new strbuf_add_oid_hex() helper function. * rs/strbuf-add-oid-hex: hex: add and use strbuf_add_oid_hex()
2026-05-25Merge branch 'ag/sequencer-remove-unused-struct-member'Junio C Hamano1-2/+0
Code clean-up. * ag/sequencer-remove-unused-struct-member: sequencer: remove todo_add_branch_context.commit
2026-05-19Merge branch 'ag/rebase-update-refs-limit-to-branches'Junio C Hamano1-1/+7
"git rebase --update-refs", when used with an rebase.instructionFormat with "%d" (describe) in it, tried to update local branch HEAD by mistake, which has been corrected. * ag/rebase-update-refs-limit-to-branches: rebase: ignore non-branch update-refs
2026-05-14hex: add and use strbuf_add_oid_hex()René Scharfe1-2/+2
Add a function for adding the full hexadecimal hash value of an object ID to a strbuf. It's thread-safe and slightly more efficient than using strbuf_addstr() with oid_to_hex() because it doesn't have to determine the length of the string or copy it from the intermediate static buffer. Add and apply a semantic patch to use it throughout the code base. I get a tiny speedup for git log showing a single hash per commit: Benchmark 1: ./git_main log --format=%H Time (mean ± σ): 91.2 ms ± 0.7 ms [User: 51.9 ms, System: 38.6 ms] Range (min … max): 89.8 ms … 92.6 ms 31 runs Benchmark 2: ./git log --format=%H Time (mean ± σ): 90.5 ms ± 0.7 ms [User: 51.0 ms, System: 38.8 ms] Range (min … max): 89.2 ms … 92.3 ms 32 runs Summary ./git log --format=%H ran 1.01 ± 0.01 times faster than ./git_main log --format=%H Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-12sequencer: remove todo_add_branch_context.commitAbhinav Gupta1-2/+0
The 'commit' field in 'struct todo_add_branch_context' is unused. It's written to, but never read from. add_decorations_to_list() gets the commit passed to it explicitly as an argument. Signed-off-by: Abhinav Gupta <mail@abhinavg.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-11rebase: ignore non-branch update-refsAbhinav Gupta1-1/+7
The following Git configuration breaks git rebase --update-refs: [rebase] instructionFormat = %s%d The '%d' format requests all available decorations for a commit, filling the global decoration table with all of them, which --update-refs then uses to populate 'update-ref' instructions in the rebase todo list. Specifically, this results in the following instruction: update-ref HEAD The todo parser then rejects the instruction: error: update-ref requires a fully qualified refname e.g. refs/heads/HEAD error: invalid line 3: update-ref HEAD To fix, ignore decorations that are not local branches when scanning through the table. This matches the documented contract: it moves branch refs under refs/heads/ and leaves display-only decorations (HEAD, tags, etc.) alone. Verification: A regression test that fails without this fix is included. Signed-off-by: Abhinav Gupta <mail@abhinavg.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-29checkout -m: autostash when switching branchesHarald Nordgren1-5/+9
When switching branches with "git checkout -m", the attempted merge of local modifications may cause conflicts with the changes made on the other branch, which the user may not want to (or may not be able to) resolve right now. Because there is no easy way to recover from this situation, we discouraged users from using "checkout -m" unless they are certain their changes are trivial and within their ability to resolve conflicts. Teach the -m flow to create a temporary stash before switching and reapply it after. On success, the stash is silently applied and the list of locally modified paths is shown, same as a successful "git checkout" without "-m". If reapplying causes conflicts, the stash is kept and the user is told they can resolve and run "git stash drop", or run "git reset --hard" and later "git stash pop" to recover their changes. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-29sequencer: teach autostash apply to take optional conflict marker labelsHarald Nordgren1-9/+29
Add label_ours, label_theirs, label_base, and stash_msg parameters to apply_autostash_ref() and the autostash apply machinery so callers can pass custom conflict marker labels through to "git stash apply --label-ours/--label-theirs/--label-base", as well as a custom stash message for "git stash store -m". Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-29sequencer: allow create_autostash to run silentlyHarald Nordgren1-6/+11
Add a silent parameter to create_autostash_internal and introduce create_autostash_ref_silent so that callers can create an autostash without printing the "Created autostash" message. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-03Merge branch 'sa/replay-revert'Junio C Hamano1-32/+46
"git replay" (experimental) learns, in addition to "pick" and "replay", a new operating mode "revert". * sa/replay-revert: replay: add --revert mode to reverse commit changes sequencer: extract revert message formatting into shared function
2026-03-25sequencer: extract revert message formatting into shared functionSiddharth Asthana1-32/+46
The logic for formatting revert commit messages (handling "Revert" and "Reapply" cases, appending "This reverts commit <ref>.", and handling merge-parent references) currently lives inline in do_pick_commit(). The upcoming replay --revert mode needs to reuse this logic. Extract all of this into a new sequencer_format_revert_message() function. The function takes a repository, the subject line, commit, parent, a use_commit_reference flag, and the output strbuf. It handles both regular reverts ("Revert "<subject>"") and revert-of-revert cases ("Reapply "<subject>""), and uses refer_to_commit() internally to format the commit reference. Update refer_to_commit() to take a struct repository parameter instead of relying on the_repository, and a bool instead of reading from replay_opts directly. This makes it usable from the new shared function without pulling in sequencer-specific state. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-19Merge branch 'lc/rebase-trailer'Junio C Hamano1-2/+50
"git rebase" learns "--trailer" command to drive the interpret-trailers machinery. * lc/rebase-trailer: rebase: support --trailer commit, tag: parse --trailer with OPT_STRVEC trailer: append trailers without fork/exec trailer: libify a couple of functions interpret-trailers: refactor create_in_place_tempfile() interpret-trailers: factor trailer rewriting
2026-03-09Merge branch 'ar/run-command-hook-take-2'Junio C Hamano1-17/+25
Use the hook API to replace ad-hoc invocation of hook scripts via the run_command() API. * ar/run-command-hook-take-2: builtin/receive-pack: avoid spinning no-op sideband async threads receive-pack: convert receive hooks to hook API receive-pack: convert update hooks to new API run-command: poll child input in addition to output hook: add jobs option reference-transaction: use hook API instead of run-command transport: convert pre-push to hook API hook: allow separate std[out|err] streams hook: convert 'post-rewrite' hook in sequencer.c to hook API hook: provide stdin via callback run-command: add stdin callback for parallelization run-command: add helper for pp child states t1800: add hook output stream tests
2026-03-06rebase: support --trailerLi Chen1-2/+50
Add a new --trailer=<trailer> option to git rebase to append trailer lines to each rewritten commit message (merge backend only). Because the apply backend does not provide a commit-message filter, reject --trailer when --apply is in effect and require the merge backend instead. This option implies --force-rebase so that fast-forwarded commits are also rewritten. Validate trailer arguments early to avoid starting an interactive rebase with invalid input. Add integration tests covering error paths and trailer insertion across non-interactive and interactive rebases. Signed-off-by: Li Chen <me@linux.beauty> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-13Merge branch 'ps/commit-list-functions-renamed'Junio C Hamano1-10/+10
Rename three functions around the commit_list data structure. * ps/commit-list-functions-renamed: commit: rename `free_commit_list()` to conform to coding guidelines commit: rename `reverse_commit_list()` to conform to coding guidelines commit: rename `copy_commit_list()` to conform to coding guidelines
2026-01-28hook: convert 'post-rewrite' hook in sequencer.c to hook APIEmily Shaffer1-17/+25
Replace the custom run-command calls used by post-rewrite with the newer and simpler hook_run_opt(), which does not need to create a custom 'struct child_process' or call find_hook(). Another benefit of using the hook API is that hook_run_opt() handles the SIGPIPE toggle logic. Signed-off-by: Emily Shaffer <emilyshaffer@google.com> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-21Merge branch 'rs/tree-wo-the-repository'Junio C Hamano1-2/+2
Remove implicit reliance on the_repository global in the APIs around tree objects and make it explicit which repository to work in. * rs/tree-wo-the-repository: cocci: remove obsolete the_repository rules cocci: convert parse_tree functions to repo_ variants tree: stop using the_repository tree: use repo_parse_tree() path-walk: use repo_parse_tree_gently() pack-bitmap-write: use repo_parse_tree() delta-islands: use repo_parse_tree() bloom: use repo_parse_tree() add-interactive: use repo_parse_tree_indirect() tree: add repo_parse_tree*() environment: move access to core.maxTreeDepth into repo settings
2026-01-15Revert "Merge branch 'ar/run-command-hook'"Junio C Hamano1-25/+17
This reverts commit f406b8955295d01089ba2baf35eceadff2d11cae, reversing changes made to 1627809eeff75e6ec936fc609e7be46d5eb2fa9e. It seems to have caused a few regressions, two of the three known ones we have proposed solutions for. Let's give ourselves a bit more room to maneuver during the pre-release freeze period and restart once the 2.53 ships.
2026-01-15commit: rename `free_commit_list()` to conform to coding guidelinesPatrick Steinhardt1-8/+8
Our coding guidelines say that: Functions that operate on `struct S` are named `S_<verb>()` and should generally receive a pointer to `struct S` as first parameter. While most of the functions related to `struct commit_list` already follow that naming schema, `free_commit_list()` doesn't. Rename the function to address this and adjust all of its callers. Add a compatibility wrapper for the old function name to ease the transition and avoid any semantic conflicts with in-flight patch series. This wrapper will be removed once Git 2.53 has been released. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-15commit: rename `reverse_commit_list()` to conform to coding guidelinesPatrick Steinhardt1-1/+1
Our coding guidelines say that: Functions that operate on `struct S` are named `S_<verb>()` and should generally receive a pointer to `struct S` as first parameter. While most of the functions related to `struct commit_list` already follow that naming schema, `reverse_commit_list()` doesn't. Rename the function to address this and adjust all of its callers. Add a compatibility wrapper for the old function name to ease the transition and avoid any semantic conflicts with in-flight patch series. This wrapper will be removed once Git 2.53 has been released. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-15commit: rename `copy_commit_list()` to conform to coding guidelinesPatrick Steinhardt1-1/+1
Our coding guidelines say that: Functions that operate on `struct S` are named `S_<verb>()` and should generally receive a pointer to `struct S` as first parameter. While most of the functions related to `struct commit_list` already follow that naming schema, `copy_commit_list()` doesn't. Rename the function to address this and adjust all of its callers. Add a compatibility wrapper for the old function name to ease the transition and avoid any semantic conflicts with in-flight patch series. This wrapper will be removed once Git 2.53 has been released. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09cocci: convert parse_tree functions to repo_ variantsRené Scharfe1-2/+2
Add and apply a semantic patch to convert calls to parse_tree() and friends to the corresponding variant that takes a repository argument, to allow the functions that implicitly use the_repository to be retired once all potential in-flight topics are settled and converted as well. The changes in .c files were generated by Coccinelle, but I fixed a whitespace bug it would have introduced to builtin/commit.c. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-12-28hook: convert 'post-rewrite' hook in sequencer.c to hook APIEmily Shaffer1-17/+25
Replace the custom run-command calls used by post-rewrite with the newer and simpler hook_run_opt(), which does not need to create a custom 'struct child_process' or call find_hook(). Another benefit of using the hook API is that hook_run_opt() handles the SIGPIPE toggle logic. Signed-off-by: Emily Shaffer <emilyshaffer@google.com> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>