merge-by-phone
Find and merge contacts that share the same phone number across different contacts.
Usage
rscontacts merge-by-phone
rscontacts merge-by-phone --fix
rscontacts merge-by-phone --fix --dry-run
What It Does
Scans all contacts and identifies groups of contacts that share one or more phone numbers. Phone numbers are normalized (digits only, stripping international prefix 00) before comparison, so +972-501234567 and 00972501234567 are treated as the same number.
Contacts are grouped using connected components: if contact A shares a phone with contact B, and contact B shares a different phone with contact C, all three are in the same merge group.
Without --fix, displays each group showing:
- All contacts in the group with full details
- Which phone numbers are shared
Fix Behavior
With --fix, for each group of N contacts you are prompted with:
[d1]elete [e1]dit [d2]elete [e2]dit ... [m]erge / [s]kip
- d1, d2, … — Delete contact 1, 2, etc. (asks for confirmation). The contact is removed from the group and the prompt re-displays with remaining contacts.
- e1, e2, … — Edit contact 1, 2, etc. using the interactive editor (same as
edit-contact). Useful for cleaning up a contact before merging. - m (merge) — Pick which contact to keep. All fields from the other contacts are merged into it, then the others are deleted.
- n (next) — Move on to the next group.
If you delete contacts until only one remains, the group is resolved automatically.
Merge Details
When merging, the command:
- Merges phone numbers — adds any phones from source contacts not already on the target (compared by normalized digits)
- Merges email addresses — adds any emails from source contacts not already on the target (compared case-insensitively)
- Merges addresses — adds any addresses not already on the target (compared by formatted value)
- Merges organization — copies from source only if the target has no organization
- Merges birthdays — copies from source only if the target has no birthday
- Merges biographies — copies from source only if the target has no biography
- Copies labels — adds all contact group memberships from source contacts to the target
- Deletes source contacts — removes the merged-away contacts
With --fix --dry-run, shows what would happen without making changes.
Notes
- Only “fixable” phone numbers are considered (see
is_fixable_phone— star codes, short codes, and alphanumeric entries are skipped). - The merge is additive for multi-value fields (phones, emails, addresses, labels) and first-wins for single-value fields (organization, birthday, biography).
- The target contact is re-fetched before updating to ensure a fresh etag, avoiding conflicts.
- This is NOT included in
check-allsince it is a destructive operation requiring careful interactive review.