Skip to content

Add entire commit command#924

Draft
pjbgf wants to merge 3 commits intomainfrom
commit
Draft

Add entire commit command#924
pjbgf wants to merge 3 commits intomainfrom
commit

Conversation

@pjbgf
Copy link
Copy Markdown
Member

@pjbgf pjbgf commented Apr 10, 2026

This command enables adding checkpoint information as a Git header directly into the Commit object:

$ entire commit -m "Improve test coverage"

Entire: Active Codex session detected
  Last prompt: Plug those three gaps

Link this commit to session context?
  [Y]es / [n]o / [a]lways (remember my choice): y
2026/04/11 00:41:24 INFO prepare-commit-msg: trailer added component=checkpoint strategy=manual-commit source=message checkpoint_id=317de6082c49
2026/04/11 00:41:24 INFO attribution calculated component=attribution agent_lines=61 human_added=0 human_modified=0 human_removed=0 total_committed=61 agent_percentage=100 accumulated_user_added=0 accumulated_user_removed=0 files_touched=1
2026/04/11 00:41:25 INFO session condensed component=checkpoint strategy=manual-commit session_id=019d7738-a66d-72a1-8a9f-c7975b0fc400 checkpoint_id=317de6082c49 checkpoints_condensed=1 transcript_lines=551
2026/04/11 00:41:25 INFO shadow branch deleted component=checkpoint strategy=manual-commit shadow_branch=entire/eab33a5-e3b0c4
[e401559] Improve test coverage

$ git cat-file -p e401559
tree b82c98e7301e14ace845ef8557b85959cf3d4341
parent eab33a570a3e86dea1f0594a8df2b9788e09254e
author Paulo Gomes <pjbgf@linux.com> 1775864484 +0100
committer Paulo Gomes <pjbgf@linux.com> 1775864484 +0100
checkpoint 317de6082c49

Improve test coverage

Entire-Checkpoint: 317de6082c49

When used, git hooks do not need to be configured.


Note

Medium Risk
Adds a new commit-writing code path that directly constructs git commit objects and updates HEAD, so bugs could create incorrect commits or refs. Changes are isolated to the new command plus a small new trailer constant and tests.

Overview
Adds a new entire commit -m command that creates a git commit via go-git, running the configured strategy commit-msg hooks to inject/normalize the Entire-Checkpoint trailer and then persisting the checkpoint ID as an extra commit header (checkpoint) when present.

The command builds the commit tree from the index, rejects empty commits (no staged changes or unchanged tree), updates HEAD to the new commit, and triggers strategy.PostCommit; it can also force-link an eligible active session by generating and appending a checkpoint ID when none was produced by the message processing.

Includes unit tests covering checkpoint trailer/header behavior, empty-commit errors, forced linking, header key constant, and registration of the new command on the root CLI.

Reviewed by Cursor Bugbot for commit e401559. Configure here.

pjbgf added 3 commits April 10, 2026 13:43
Entire-Checkpoint: fc09dbaa3a88
Entire-Checkpoint: 317de6082c49
Copilot AI review requested due to automatic review settings April 10, 2026 23:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new entire commit subcommand that creates Git commits via go-git while embedding Entire checkpoint metadata directly in the commit object (extra header), reducing reliance on external Git hook configuration.

Changes:

  • Register a new entire commit Cobra command on the root CLI.
  • Introduce a dedicated commit-object extra header key (checkpoint) alongside the existing commit-message trailer.
  • Add unit tests covering header/trailer writing, empty-commit behavior, and root command registration.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
cmd/entire/cli/trailers/trailers.go Adds CheckpointHeaderKey constant for commit extra headers.
cmd/entire/cli/root.go Registers the new commit command with the root CLI.
cmd/entire/cli/commit.go Implements commit creation (tree from index, commit encode/store, HEAD update) and checkpoint header/trailer handling.
cmd/entire/cli/commit_test.go Adds tests validating trailer/header behavior and command wiring.

Comment thread cmd/entire/cli/commit.go
Comment on lines +184 to +187
if len(idx.Entries) == 0 {
return plumbing.ZeroHash, git.ErrEmptyCommit
}

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildCommitTreeFromIndex treats an empty index (len(idx.Entries) == 0) as git.ErrEmptyCommit, which blocks valid commits that delete all tracked files (the resulting tree is empty, but differs from the previous tree). Instead, build an empty tree hash (via checkpoint.BuildTreeFromEntries with an empty map) and let the existing treeHash == previousTree check determine whether the commit is truly empty.

Suggested change
if len(idx.Entries) == 0 {
return plumbing.ZeroHash, git.ErrEmptyCommit
}

Copilot uses AI. Check for mistakes.
Comment thread cmd/entire/cli/commit.go
Comment on lines +35 to +41
hash, err := runCommit(cmd.Context(), message)
if err != nil {
return err
}

fmt.Fprintf(cmd.OutOrStdout(), "[%s] %s\n", shortCommitHash(hash), firstLine(message))
return nil
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command output uses firstLine(message) from the original -m value, but hooks (PrepareCommitMsg/CommitMsg) can modify the final commit message subject. Consider printing the first line of the final message (or reading back the created commit’s subject) so the displayed summary matches what was actually committed.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Redundant duplicate call to force checkpoint logic
    • Removed the dead code block in runCommit (lines 60-69) that redundantly called forceCheckpointIDForActiveSession, since prepareEntireCommitMessage already handles this case and no state changes between the two calls.

Create PR

Or push these changes by commenting:

@cursor push 4a3db96ebe
Preview (4a3db96ebe)
diff --git a/cmd/entire/cli/commit.go b/cmd/entire/cli/commit.go
--- a/cmd/entire/cli/commit.go
+++ b/cmd/entire/cli/commit.go
@@ -57,16 +57,6 @@
 		return plumbing.ZeroHash, err
 	}
 	checkpointID = resolveCommitCheckpointID(finalMessage, checkpointID)
-	if checkpointID == "" {
-		forcedCheckpointID, forceErr := forceCheckpointIDForActiveSession(ctx)
-		if forceErr != nil {
-			return plumbing.ZeroHash, forceErr
-		}
-		if !forcedCheckpointID.IsEmpty() {
-			checkpointID = forcedCheckpointID.String()
-			finalMessage = trailers.FormatCheckpoint(finalMessage, forcedCheckpointID)
-		}
-	}
 
 	treeHash, err := buildCommitTreeFromIndex(ctx, repo)
 	if err != nil {

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e401559. Configure here.

Comment thread cmd/entire/cli/commit.go
checkpointID = forcedCheckpointID.String()
finalMessage = trailers.FormatCheckpoint(finalMessage, forcedCheckpointID)
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant duplicate call to force checkpoint logic

Low Severity

forceCheckpointIDForActiveSession is called in prepareEntireCommitMessage (which also calls trailers.FormatCheckpoint on success) and again in runCommit. The second call in runCommit is effectively dead code — it only executes when checkpointID is empty, which means prepareEntireCommitMessage already called forceCheckpointIDForActiveSession and got an empty result. Since no state changes between the two calls, the second invocation always returns the same empty result. This duplicated force-and-format logic across both functions makes the code harder to reason about and maintain.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e401559. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants