SQUASH vs ITERATIVE
SQUASH vs ITERATIVE
Section titled “SQUASH vs ITERATIVE”Two workflow modes that push directly to the destination, with different approaches to commit history.
Visual Comparison
Section titled “Visual Comparison”SQUASH Mode
Section titled “SQUASH Mode”ITERATIVE Mode
Section titled “ITERATIVE Mode”Feature Comparison
Section titled “Feature Comparison”| Feature | SQUASH | ITERATIVE |
|---|---|---|
| Commits created | 1 per sync | 1 per origin commit |
| History preserved | No | Yes |
| Handles merges | Gracefully | May fail |
| Bisect-friendly | No | Yes |
| Initial sync speed | Fast | Slower |
| Complexity | Low | Higher |
When to Use SQUASH
Section titled “When to Use SQUASH”Recommended for most workflows. Use SQUASH when:
- Destination history doesn’t need to match origin
- You have complex merge histories
- You want cleaner destination history
- You’re syncing frequently (avoid commit spam)
- You’re just mirroring without bidirectional sync
core.workflow( name = "export", mode = "SQUASH", ...)SQUASH Commit Messages
Section titled “SQUASH Commit Messages”Copybara creates informative commit messages:
Project import generated by Copybara.
Changes:- fix: correct validation logic- feat: add user authentication- docs: update README
GitOrigin-RevId: abc123def456You can customize with metadata.squash_notes():
transformations = [ metadata.squash_notes( prefix = "Sync from internal:\n\n", show_author = True, show_description = True, oldest_first = True, ),]When to Use ITERATIVE
Section titled “When to Use ITERATIVE”Use ITERATIVE when:
- You need exact commit-to-commit mapping
- Auditing requires preserved history
- You need to
git bisecton the destination - Each commit must be individually traceable
- Linear history in origin (no merges)
core.workflow( name = "export", mode = "ITERATIVE", ...)ITERATIVE Commit Messages
Section titled “ITERATIVE Commit Messages”Each destination commit includes:
Original commit message here
GitOrigin-RevId: abc123Handling Merge Commits
Section titled “Handling Merge Commits”SQUASH Behavior
Section titled “SQUASH Behavior”Merge commits are handled transparently - all changes are combined:
ITERATIVE Behavior
Section titled “ITERATIVE Behavior”Merge commits can cause issues:
Performance Comparison
Section titled “Performance Comparison”Initial Sync
Section titled “Initial Sync”| Mode | 100 commits | 1000 commits | 10000 commits |
|---|---|---|---|
| SQUASH | Fast | Fast | Fast |
| ITERATIVE | Moderate | Slow | Very slow |
SQUASH processes all changes at once; ITERATIVE must process each commit individually.
Incremental Syncs
Section titled “Incremental Syncs”Both modes perform similarly for incremental syncs (only new commits are processed).
Configuration Examples
Section titled “Configuration Examples”SQUASH with Custom Notes
Section titled “SQUASH with Custom Notes”core.workflow( name = "export-squash", mode = "SQUASH", transformations = [ metadata.squash_notes( prefix = "Weekly sync from internal:\n\n", show_author = True, show_description = True, ), metadata.add_header("Synced-From: internal"), ], ...)ITERATIVE with Author Mapping
Section titled “ITERATIVE with Author Mapping”core.workflow( name = "export-iterative", mode = "ITERATIVE", transformations = [ metadata.map_author({ "internal@corp.com": "external@example.com", }), metadata.expose_label("Reviewed-by"), ], ...)Decision Flowchart
Section titled “Decision Flowchart”Switching Between Modes
Section titled “Switching Between Modes”You can switch modes between syncs, but be aware:
- SQUASH → ITERATIVE: Works, but you’ll lose the “squash” point in history
- ITERATIVE → SQUASH: Works, subsequent sync will squash all new changes
The state tracking (via GitOrigin-RevId) works across mode changes.