Skip to content

feat(record): add --before flag to insert commit before current HEAD#1663

Draft
claytonrcarter wants to merge 8 commits into
arxanas:masterfrom
claytonrcarter:record-before
Draft

feat(record): add --before flag to insert commit before current HEAD#1663
claytonrcarter wants to merge 8 commits into
arxanas:masterfrom
claytonrcarter:record-before

Conversation

@claytonrcarter
Copy link
Copy Markdown
Collaborator

wip, currently includes #1612

@claytonrcarter claytonrcarter changed the title wip: record --before feat(record): add --before flag to insert commit before current HEAD May 19, 2026
@claytonrcarter claytonrcarter force-pushed the record-before branch 3 times, most recently from 540f876 to 9f05cb2 Compare May 20, 2026 03:15
DUMMY_DATE is used to populate GIT_AUTHOR_DATE and GIT_COMMITTER_DATE, both of
which expect dates in RFC2822 format, but DUMMY_DATE was itselt not in RFC2822
format, and it was made less so by appending a 2 digit timezone offset.

This has not been an issue thus far because we were only passing the date to
git as a string, and git seems to be fairly liberal when parsing dates. `git
record --new` seems to be the first time we're actually creating wholey new
commits (vs just modifying existing commits), so we need to set a current time
on these new commits. To do so, we need to parse DUMMY_DATE into a SystemTime
with chrono, and chrono is not lenient when parsing dates, leading to various
errors:

1. The existing format yielded Invalid, because of the time/year order.
2. Fixing the order of the year led to TooShort, because of the 2 digit
   timezone offset.
3. Fixing the timezone offset yielded Impossible, because 2020-10-29 was
   not a Wednesday.

Fun! Regardless, I don't expect these changes to have any impact outside of
the upcoming tests for `record --new`.

Old format: Wed 29 Oct 12:34:56 2020 PDT -02
New format: Thu, 29 Oct 2020 12:34:56 -0200

Ref: https://github.com/git/git/blob/master/Documentation/date-formats.adoc
Ref: https://www.rfc-editor.org/rfc/rfc2822#section-3.3
`record --new` is the first feature in which we create entirely new
commits (vs rewriting or splitting existing commits) and I was running
into test failures in CI that seemed to only differ by timezone.
Explicitly setting the time zone in the test git environment resolved
the issue.
Fixes various defects encountered during testing.
Prep only, no logic changes yet.
Prep only, no logic changes. This sould make the next diff more concise.
When --before is used:
1. The commit C is created normally as a child of HEAD (B).
2. A c_alt commit is created in-memory as a child of B's parent (A),
   with the same tree and metadata as C.
3. A RewriteEvent records C as obsolete (replaced by c_alt).
4. `git reset --soft HEAD~` moves HEAD back to B, orphaning C and
   making it invisible in the DAG (preventing constraint cycles).
5. A rebase plan moves B to be a child of c_alt, yielding B'.

The result is A <- c_alt <- B', with HEAD and any branch tracking B'.

Four test cases covering the new --before behaviour:

- test_record_before: basic happy path - working-copy changes are
  inserted before HEAD as a new commit; HEAD (and its branch) advance
  to the rebased original HEAD.
- test_record_before_with_new: --new --before inserts an empty commit
  before HEAD and rebases HEAD on top of it.
- test_record_before_rewrite_public_commit: warns when HEAD is a public
  commit and prints a specific `git move` invocation to force-proceed.
- test_record_before_merge_conflict: conflict during the rebase of HEAD
  is surfaced with the Before remediation message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant