Skip to content

feat: add sync command to merge default branch into current branch#39

Merged
alexandreafj merged 4 commits into
masterfrom
feat/add-sync-command
May 29, 2026
Merged

feat: add sync command to merge default branch into current branch#39
alexandreafj merged 4 commits into
masterfrom
feat/add-sync-command

Conversation

@alexandreafj
Copy link
Copy Markdown
Owner

What

Adds a new top-level command, gitm sync, that merges the latest default branch (main/master, auto-detected per repo) into whatever branch each selected repository is currently on — across one or many repos in parallel.

Why

Updating a feature branch with the latest master/main was a manual, repetitive chore: run gitm checkout master -r <repo>, then cd into the repo folder and git merge master by hand, repeated for every repo. This is exactly the kind of multi-repo git operation gitm exists to automate.

How it works

For each selected repo (in parallel via runner.Run):

  1. Auto-detects the default branch from the stored repo.DefaultBranch (set at repo add).
  2. Skips repos with uncommitted changes (stash/commit first).
  3. Skips repos already on their default branch (points to gitm update for pulling).
  4. Fetches the latest default branch from origin, then merges origin/<default> into the current branch (falls back to the local default branch when there's no remote).
  5. Leaves merge conflicts in place and reports them with paths, so they can be resolved manually. A conflict is an expected outcome, not a hard failure — the command still exits 0.

Selection modes (consistent with checkout / branch)

  • gitm sync — interactive TUI multi-select
  • gitm sync --repo a,b / -r a,b — named repos, no prompt
  • gitm sync --all / -a — every repo, no prompt

Changes

  • internal/git/git.go: new Merge and UnmergedFiles primitives (only new git ops needed).
  • internal/cli/sync.go: new command + runSyncWithUI workflow.
  • internal/cli/root.go: register syncCmd().
  • README.md: ToC entry, full command reference, project-structure tree.

Testing

  • internal/git/merge_test.go: clean merge, conflict (left in merging state), clean-repo unmerged check.
  • internal/cli/sync_test.go: command wiring, happy-path merge, dirty skip, on-default skip, conflict-left-in-place, --repo/--all bypass TUI, no-repos.
  • All real temp git repos (no mocks, per AGENTS.md). Full suite passes with -race: go test ./... -race → 447 passed across 8 packages. make lint clean.

🤖 Generated with Claude Code

Updating a feature branch with the latest master/main was a manual chore:
run `gitm checkout master -r <repo>`, then cd into each repo and
`git merge master` by hand, repeated per repo. `gitm sync` automates this
across selected repos in parallel — interactively, or via --repo/--all.

For each repo it auto-detects the default branch (main/master) from the
stored value, skips dirty repos and repos already on the default branch,
fetches the latest default from origin, and merges origin/<default> into the
current branch. Merge conflicts are intentionally left in place and reported
so the user can resolve them, rather than aborting or failing the whole run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 29, 2026 08:13
@github-actions
Copy link
Copy Markdown

✅ All checks passed (Go 1.26)

Coverage: 69.9%

Copy link
Copy Markdown

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 gitm sync command to merge each selected repository’s default branch into its current branch, fitting into the existing multi-repo CLI workflow.

Changes:

  • Adds sync command wiring, selection modes, merge workflow, conflict reporting, and tests.
  • Adds git merge/unmerged-file primitives with real-repo tests.
  • Updates README command reference and root command registration tests.

Reviewed changes

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

Show a summary per file
File Description
README.md Documents gitm sync and updates project structure.
internal/git/git.go Adds merge and unmerged-file helpers.
internal/git/merge_test.go Tests merge success, conflicts, and clean unmerged checks.
internal/cli/sync.go Implements the new sync command workflow.
internal/cli/sync_test.go Tests sync command flags and core repo behavior.
internal/cli/root.go Registers the sync command.
internal/cli/root_test.go Updates expected subcommands.

Comment thread internal/cli/sync.go Outdated
Comment thread internal/cli/sync.go Outdated
Comment thread internal/cli/sync.go Outdated
Comment thread internal/cli/sync.go Outdated
The Test Stats table had drifted (38 files / 330 functions): test functions
were added since the stats landed in #34 without updating the count, and this
branch adds two test files (merge_test.go, sync_test.go). Counts exclude the
single TestMain harness entry point, which is not a test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

✅ All checks passed (Go 1.26)

Coverage: 69.9%

…fallback

Resolves four review findings on the new sync command:

- Require a fully clean working tree (git.IsDirty) instead of tracked-only.
  A merge can be blocked by an untracked file that collides with a path the
  default branch introduces, so untracked changes must skip the repo too —
  IsDirtyTrackedOnly is documented as safe only when untracked files pose no
  conflict risk, which is not the case for a merge.
- Return a non-zero error when runner.HasErrors, matching the other multi-repo
  commands. Real failures (status/branch errors, non-conflict merge errors) now
  surface; merge conflicts remain intentional skips that still exit 0.
- Stop printing the fetch-failure warning from inside the parallel worker
  (which could interleave with the runner's synchronized output) and fold it
  into the returned result message instead.
- Prefer origin/<default> only when the fetch succeeded; on a failed/offline
  fetch fall back to the local default branch rather than silently merging a
  stale remote-tracking ref.

Adds tests for the untracked-skip and error-exit paths; refreshes test stats.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 29, 2026 08:29
@github-actions
Copy link
Copy Markdown

✅ All checks passed (Go 1.26)

Coverage: 69.9%

Copy link
Copy Markdown

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

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

Comment thread internal/cli/sync.go Outdated
Comment thread README.md Outdated
The sync help text and README described the manual workflow as
`gitm checkout master` followed by `git merge master`, but that sequence
leaves you on the default branch and makes the merge a no-op. Reword both to
describe what sync actually replaces: pulling the latest master/main and
merging it into your working branch by hand, per repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

✅ All checks passed (Go 1.26)

Coverage: 69.9%

@alexandreafj alexandreafj merged commit 58b6fa4 into master May 29, 2026
1 check passed
@alexandreafj alexandreafj deleted the feat/add-sync-command branch May 29, 2026 09:06
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.

2 participants