workspace.export: add base_commit to capture worker git commits

Without base_commit, export diffs against the current guest HEAD.
If the worker ran git commit inside the VM, HEAD advanced and the
diff came back empty — committed work was silently lost.

With base_commit set to the head_commit from workspace.prepare,
the diff uses that fixed point instead. After git add -A the index
holds the full working state, so git diff --cached <base_commit>
captures everything: committed deltas (HEAD moved past base) and
any uncommitted changes on top, in one patch, applied with the
same git apply flow.

- WorkspaceExportParams gains base_commit
- WorkspaceExportResult echoes back the ref actually used
- CLI gains --base-commit flag
- Tests assert scripts use the caller-supplied ref and that
  omitting it falls back to HEAD
This commit is contained in:
Thales Maciel 2026-04-14 16:13:05 -03:00
parent 94c353f317
commit ff51b7ce21
No known key found for this signature in database
GPG key ID: 33112E6833C34679
6 changed files with 162 additions and 10 deletions

View file

@ -941,13 +941,15 @@ func newVMWorkspacePrepareCommand() *cobra.Command {
func newVMWorkspaceExportCommand() *cobra.Command {
var guestPath string
var outputPath string
var baseCommit string
cmd := &cobra.Command{
Use: "export <id-or-name>",
Short: "Pull changes from a guest workspace back to the host as a patch",
Long: "Stage all changes inside the guest workspace (git add -A) and emit a binary-safe unified diff against HEAD. With no --output flag the patch is written to stdout so it can be piped directly to git apply.",
Long: "Stage all changes inside the guest workspace (git add -A) and emit a binary-safe unified diff. Pass --base-commit with the head_commit from workspace prepare to capture changes even when the worker ran git commit inside the VM. Without --base-commit the diff is against the current guest HEAD, which misses committed changes.",
Args: exactArgsUsage(1, "usage: banger vm workspace export <id-or-name>"),
Example: strings.TrimSpace(`
banger vm workspace export devbox | git apply
banger vm workspace export devbox --base-commit abc1234 | git apply
banger vm workspace export devbox --output worker.diff
banger vm workspace export devbox --guest-path /root/project --output changes.diff
`),
@ -957,8 +959,9 @@ func newVMWorkspaceExportCommand() *cobra.Command {
return err
}
result, err := vmWorkspaceExportFunc(cmd.Context(), layout.SocketPath, api.WorkspaceExportParams{
IDOrName: args[0],
GuestPath: guestPath,
IDOrName: args[0],
GuestPath: guestPath,
BaseCommit: baseCommit,
})
if err != nil {
return err
@ -981,6 +984,7 @@ func newVMWorkspaceExportCommand() *cobra.Command {
}
cmd.Flags().StringVar(&guestPath, "guest-path", "/root/repo", "guest workspace path")
cmd.Flags().StringVar(&outputPath, "output", "", "write patch to this file instead of stdout")
cmd.Flags().StringVar(&baseCommit, "base-commit", "", "diff from this commit (use head_commit from workspace prepare to capture worker git commits)")
return cmd
}