Skip to content

✨ feat(worktree): add sync command and --sync option#34

Merged
samzong merged 1 commit intomainfrom
feat-wt-add-autosync
Jan 7, 2026
Merged

✨ feat(worktree): add sync command and --sync option#34
samzong merged 1 commit intomainfrom
feat-wt-add-autosync

Conversation

@samzong
Copy link
Owner

@samzong samzong commented Jan 7, 2026

No description provided.

Signed-off-by: samzong <samzong.lu@gmail.com>
@gemini-code-assist
Copy link

Summary of Changes

Hello @samzong, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the gmc worktree functionality by introducing a new sync command and integrating a --sync option into the add command. These additions are designed to simplify and automate the process of keeping worktree base branches synchronized with their remote sources. The sync operation performs a fast-forward update and intelligently handles pushing changes to the 'origin' remote when 'upstream' is designated as the primary synchronization source, thereby fostering a more efficient and current development workflow.

Highlights

  • New gmc wt sync command: A dedicated command has been introduced to synchronize the base branch of worktrees, ensuring it is up-to-date with its remote counterpart.
  • --sync option for gmc wt add: The worktree creation process now includes a --sync option, which automatically synchronizes the base branch before a new worktree is added, streamlining the setup.
  • Enhanced Base Branch Resolution: The logic for determining the base branch for sync operations has been refined to prioritize origin/HEAD over upstream/HEAD, with robust fallbacks to main or master local branches.
  • Comprehensive Documentation Updates: All relevant man pages and the README.md have been updated to reflect the new commands, options, and their usage, ensuring clear guidance for users.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a sync command for worktrees and a --sync option for the add command, which is a valuable feature for keeping base branches up-to-date. The implementation is generally solid and includes good test coverage for the new functionality. However, I've identified a few areas for improvement. There's an inconsistency in how origin and upstream remotes are prioritized, which could affect fork-based workflows. Additionally, there are a couple of opportunities to improve code organization and avoid state mutation for better maintainability. My detailed comments below provide specific suggestions to address these points.

Comment on lines +121 to 126
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/upstream/HEAD"); ref != "" {
return ref, nil
}

Choose a reason for hiding this comment

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

high

The logic for resolving the base branch now prefers origin over upstream. In a typical forked repository workflow, upstream represents the main source of truth, and developers sync from it. The selectSyncRemote function in sync.go correctly prefers upstream. To maintain consistency and support forked workflows correctly, upstream should be checked before origin when determining the base branch.

I suggest swapping the order of these checks.

Suggested change
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/upstream/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/upstream/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
return ref, nil
}

Comment on lines +190 to +195
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/upstream/HEAD"); ref != "" {
return ref, nil
}

Choose a reason for hiding this comment

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

high

This logic prefers origin over upstream when resolving the base branch name. However, selectSyncRemote prefers upstream when selecting a remote to fetch from. In a standard forked repository workflow, upstream is the canonical source of truth. For consistency, upstream should be preferred here as well when determining the base branch name.

I recommend swapping the order of these checks to prioritize upstream.

Suggested change
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/upstream/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/upstream/HEAD"); ref != "" {
return ref, nil
}
if ref := c.gitSymbolicRef(repoDir, "refs/remotes/origin/HEAD"); ref != "" {
return ref, nil
}

Comment on lines +9 to +29
wtAddSync bool
wtSyncBase string
wtSyncDryRun bool
)

var wtSyncCmd = &cobra.Command{
Use: "sync",
Short: "Sync the base branch used for worktrees",
Long: `Sync the base branch used for worktrees.

This updates the base branch using fast-forward only and optionally
updates the base worktree when it's clean.`,
RunE: func(cmd *cobra.Command, args []string) error {
wtClient := worktree.NewClient(worktree.Options{Verbose: verbose})
return runWorktreeSync(wtClient)
},
}

func init() {
wtCmd.AddCommand(wtSyncCmd)
wtAddCmd.Flags().BoolVar(&wtAddSync, "sync", false, "Sync base branch before creating worktree")

Choose a reason for hiding this comment

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

medium

The wtAddSync flag variable is defined here, and the flag is registered for wtAddCmd in this file's init function. This is confusing because the flag belongs to the add command, which is defined in cmd/worktree.go. For better code organization and maintainability, flag variables and their registrations should be co-located with the command they belong to. I recommend moving the wtAddSync variable definition and the wtAddCmd.Flags().BoolVar(...) call to cmd/worktree.go.

Comment on lines +52 to +58
origDir := c.runner.Dir
if repoDir != "" {
c.runner.Dir = repoDir
defer func() {
c.runner.Dir = origDir
}()
}

Choose a reason for hiding this comment

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

medium

The Sync function temporarily mutates the c.runner.Dir field. This is not thread-safe and can lead to subtle bugs if the Client is ever used concurrently. A better approach would be to avoid mutating the client's state. Since other git commands in this function use the -C flag to specify the directory, consider refactoring c.List() to also accept a directory parameter, which would make this state mutation unnecessary.

@samzong samzong merged commit c412e14 into main Jan 7, 2026
1 check passed
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