TurtleGit for Mac

View Markdown source ↗

Add commits to Rebase / Cherry Pick

This records a partial native port at pinned TortoiseGit revision 7338078f8ddd924b8cddee35f512f2286072136d.

Source behavior

RebaseDlg.cpp::OnBnClickedButtonAdd opens CLogDlg in selection mode, allows multiple selection and leaves the plan unchanged on Cancel. It loads the selected commits, assigns Pick and inserts them above the existing newest-first list. Repeated commits are permitted. Add is disabled during replay and with Preserve Merges. LogDlg.cpp returns selected hashes in visible row order.

Native implementation

Add now opens the native Log window as a sheet, with multiple-selection OK/Cancel. The same Log search/history controls and original action artwork are used. Existing single-selection pickers keep their behavior; their callbacks are explicitly labeled to avoid ambiguous trailing-closure matching.

Accepted rows are resolved to immutable commit objects and inserted above the current visible plan in picker order. Their replay follows the existing entries, oldest first. Existing actions, destination hashes, branch identity and attribution options are retained. New rows default to Pick. Cancel and empty selections leave the plan unchanged; failures are atomic. The parent plan cannot start or receive another handoff while the sheet is open. Pending handoffs resume after selection and any resulting insertion have completed.

Repeated commits have distinct row identities. These identities and source hashes are written by the application's headless sequence editor into worktree-local replay metadata before execution. The Git todo contains commit hashes, not row identifiers. Edit/conflict recovery keeps the original commit hash and separately identifies the stopped occurrence, so selection and remaining rows remain distinct after reopening. Git removes that metadata when the session ends.

An added plan becomes executable even when the original Rebase was up to date. The backend forces the custom todo to run while preserving the user's Force Rebase checkbox value. Capture validation still rejects stale references and malformed plans. Active replay and Preserve Merges disallow additions.

Add before a plan is loaded

Add remains enabled while branch/upstream are incomplete or invalid, matching the upstream Choose Branch state. Accepted revisions become an editable draft with numbered rows, actions, ordering and file/message inspection. Cancel retains that draft. Start stays disabled until a valid destination plan is captured; resolving and editing draft entries changes no HEAD, reference, index or working file.

Changing the references rebuilds the commit list from those references, as upstream FetchLogList does. That replaces earlier draft entries; choose the references and then Add again to include commits outside the generated range. If Add supersedes an in-flight reload with valid references, the backend captures a fresh plan and appends the accepted selections instead of leaving the window without a runnable plan. Incomplete references remain a draft without an interrupting revision alert.

Evidence and limits

20 focused RebaseTests pass: the earlier Rebase/Cherry Pick coverage plus picker insertion order, repeated identities, actual replay, repeated Edit/reopening/ Continue, up-to-date Rebase execution, Preserve Merges rejection and atomic draft resolution with unchanged HEAD/index. The native receiver additionally checks multiple-selection acceptance/order/guards, original single-selection behavior, Add cancellation, default actions, duplicate rows and recovery selection. System and packaged Git checks, build/package audits and exact source hashes for the latest draft work are recorded in qa/rebase-draft-add-2026-10-06.json; the previous c86aa06 checkpoint is recorded in qa/rebase-add-2026-10-06.json.

The native receiver hosts real views without displayed windows; it injects picker results rather than displaying and clicking the actual sheet. Displayed picker focus, close/OK/Cancel gestures and screenshot acceptance remain unverified. Preserve Merges customization, Split and complete conflict/ squash controls remain pending. Signed App Store execution is not established.

Owned Add and merge-parent preparation — October 16, 2026

Add now owns a cancellable preparation lifetime from the accepted picker rows through commit resolution and any missing destination-plan capture. Core Add APIs carry cancellation through session checks and every commit read. The native plan and editable draft publish only after all reads succeed; Cancel, failure, changed initiating inputs and forced closure retain the prior complete rows, actions and selection. The busy/preparation and global Quit ownership last until the actual worker returns, including a cancelled successful reply already in flight. A failed Add can be retried without losing the original plan. No references, index or working files are changed by this preparation.

The Add Log inherits the owner's preferences and owns a distinct multiple-selection request. It retires and detaches before starting insertion; retained callbacks, refused presentation and forced parent closure cannot insert a second selection or leave the parent locked. Picker ownership itself prevents Quit while open. Ordinary selectable Log commands remain available, as in source SetSelect(true). The source insertion order, repeated occurrence IDs, Pick defaults and incomplete- reference draft behavior are retained.

At this October 16 checkpoint, Cherry Pick merge-parent preparation shared the cancellable read ownership. Parent metadata used the same token as its native question. Cancel settles an owned question once; forced closure cancels reads and settles the continuation. The captured plan receives mainlines only after every choice succeeds and the initiating plan is still current. Cancel on a later merge therefore discards the whole tentative set of choices. Invalid or stale replies cannot start replay. That checkpoint retained the native preflight adaptation; upstream asks just in time inside RebaseDlg.cpp around lines 2115–2135. The later reached-parent continuation supersedes that preflight behavior without changing the historical validation below. Upstream Add is OnBnClickedButtonAdd around lines 3082–3125.

The Debug build passed. Six focused Core tests passed cumulatively: the initial run passed five; its started-Add fixture intercepted the wrong Git subcommand. Correcting that helper and rerunning only that case passed without a product change. Six grouped native cases passed with system/bundled Git: new preparation, retained action/replay and reference ownership. The first native attempt required LocalizedError conformance for the fixture's exact error-message assertion; the assertion was retained. All seven attempted receivers were reaped and independently absent. No app rebuild or complete Core rerun followed either fixture repair. Batch evidence records results and headless reference split-view warnings. Physical picker focus/keyboard/VoiceOver and native visual comparisons, full multi-merge and hook/editor behavior, signed Finder and App Store execution remain open. This is partial family parity, not complete Rebase or application acceptance.

Reached merge-parent continuation — October 25, 2026

The reached-parent family replaces the earlier all-parents-before-Start sweep with per-occurrence questions at the actual advanced Cherry Pick execution boundary. Earlier rows can execute first; Skip bypasses the question, empty-subject review retains its source order, and accepted mainlines persist through cancellation/reopening under session/HEAD/replay-file guards. All supported parents remain available as a native extension beyond the source's first two buttons. Add's independent atomic insertion remains unchanged. The new checkpoint records cumulative focused Core and paired native engine passes; October 16 preparation results remain historical.

The same continuation keeps unresolved merge/dependent Squash rows as owned physical placeholders until the reached choice is accepted, while native rows retain requested actions. Its documented orphan-Squash boundary retains explicit stopped-plan recovery if Skip removes the first retained group leader; dependent work is not silently discarded. That boundary remains open after the focused validation.