Twin can automatically set up git remotes between your local and remote directories when both are git repositories. This makes it easy to sync files with rsync while also being able to push/pull git commits between machines.
- How It Works
- Quick Start
- Command-Line Flags
- Interactive Prompts
- Remote Naming
- Conflict Resolution
- Configuration
- Working with Git After Setup
- Examples
When you pair a local git repository with a remote git repository during initial pairing, Twin will:
- Detect that both directories are git repositories
- Prompt you for remote names (or use defaults/flags)
- Add each repository as a git remote on the other machine bidirectionally
- Save the configuration for future syncs
The git remote setup only runs once during initial pairing unless you force it with -g.
# Both directories are git repos
cd ~/my-project
twin myserver /remote/project
# Twin prompts:
# Git repositories detected! Setting up git remotes.
#
# Choose how to name the remote on the local machine:
# 1) Use default name: target
# 2) Enter custom name
# 3) Use SSH config hostname: server.example.com
#
# Choice (1-3) [1]:
# After selecting option 1 for both prompts:
# Local repo now has remote 'target' -> myserver:/remote/project
# Remote repo now has remote 'source' -> youruser@yourmachine:~/my-project
# Now you can use git commands:
git fetch target
git pull target main
git push target mainControl git integration behavior with these flags:
twin -g myserver # Force git remote setup (even if already paired)
twin -G myserver # Skip git remote setup entirelytwin --git-local-name laptop myserver
# Local machine will have remote named 'laptop' instead of 'target'
twin --git-remote-name desktop myserver
# Remote machine will have remote named 'desktop' instead of 'source'
# Combine both:
twin --git-local-name dev --git-remote-name prod myservertwin --git-ssh-config myserver
# Uses hostname from ~/.ssh/config as remote name
# If SSH config has 'HostName server.example.com', uses that nametwin -g --git-local-name laptop --git-remote-name server myserver
# Forces setup with custom names on both sidesIf you don't provide remote names via flags, Twin asks interactively:
Git repositories detected! Setting up git remotes.
Choose how to name the remote on the local machine:
1) Use default name: target
2) Enter custom name
3) Use SSH config hostname: 192.168.0.75
Choice (1-3) [1]:
Uses "target" for local machine, "source" for remote machine.
Choice (1-3) [1]: 2
Enter custom remote name: production
# Remote will be named 'production'
Uses the hostname from your SSH config. If the SSH config has:
Host myserver
HostName server.example.com
Twin will suggest "server.example.com" as the remote name.
Without custom names:
- Local machine gets remote named:
target - Remote machine gets remote named:
source
Rationale: You're on the source machine targeting a remote.
Provide specific names for clarity:
# Development workflow
twin --git-local-name staging myserver
# Multi-machine setup
twin --git-local-name laptop desktop
twin --git-local-name desktop laptopUse actual hostnames for meaningful remote names:
twin --git-ssh-config prod-server
# If SSH config has HostName: production.example.com
# Remote will be named: production.example.comIf a git remote with the chosen name already exists, Twin handles it gracefully:
Warning: Git remote 'target' already exists on local machine.
Enter alternate name (or press Enter to skip git remote setup):
Options:
- Enter alternate name:
target2,myserver, etc. - Press Enter: Skip git remote setup entirely
- Use
-gflag later: Force git setup after resolving conflicts manually
cd ~/my-project
git remote -v
# origin https://github.com/user/repo.git (fetch)
# origin https://github.com/user/repo.git (push)
# target myserver:/remote/project (fetch)
# target myserver:/remote/project (push)Git integration settings are stored in .twin.{remote}.json:
{
"remote_path": "/var/www/myapp",
"rsync_flags": "-avu --progress",
"last_sync": "2025-11-23T10:30:00",
"git_integration": {
"local_remote_name": "target",
"remote_remote_name": "source",
"setup_complete": true
}
}local_remote_name: Name of remote on local machineremote_remote_name: Name of remote on remote machinesetup_complete: Whether git setup has been completed
# Fetch from remote
git fetch target
# Pull changes from remote
git pull target main
# Push to remote
git push target main
# View all remotes
git remote -vSSH to the remote and use the reverse remote:
ssh myserver
cd /remote/project
# Fetch from your local machine
git fetch source
# Pull changes from your local machine
git pull source main
# Push to your local machine
git push source main# On local machine
git add .
git commit -m "Add feature"
git push target main
# On remote machine (via SSH)
ssh myserver
cd /remote/project
git pull source maincd ~/my-project
twin myserver /remote/project
# Choose option 1 for both prompts
# Result:
# - Local: remote 'target' -> myserver:/remote/project
# - Remote: remote 'source' -> you@yourmachine:~/my-projecttwin --git-local-name laptop --git-remote-name server myserver /remote/project
# No prompts, uses custom names
# Result:
# - Local: remote 'laptop' -> myserver:/remote/project
# - Remote: remote 'server' -> you@yourmachine:~/my-project# ~/.ssh/config has:
# Host prod
# HostName production.example.com
twin --git-ssh-config prod /var/www/app
# Result:
# - Local: remote 'production.example.com'
# - Remote: remote 'yourhostname'twin -G myserver /remote/project
# Sets up file sync only, no git remotes# Already paired, but want to set up git remotes now
twin -g myserver
# Runs git setup even though directory is already pairedtwin myserver /remote/project
# Git repositories detected! Setting up git remotes.
#
# Choose how to name the remote on the local machine:
# 1) Use default name: target
# 2) Enter custom name
# 3) Use SSH config hostname: 192.168.0.75
#
# Choice (1-3) [1]: 1
#
# Warning: Git remote 'target' already exists on local machine.
# Enter alternate name (or press Enter to skip git remote setup): staging
#
# Remote added: staging -> myserver:/remote/projectTwin intelligently chooses the git remote URL format:
For remote machines:
myserver:/path/to/repo
user@host:/path/to/repo
For same machine (rare, but supported):
/path/to/repo
Twin gracefully handles non-git directories:
- Neither is a git repo: Syncs files normally, no git setup attempted
- Only one is a git repo: Syncs files normally, no git setup attempted
- No errors or warnings: Git integration is silent when not applicable
Problem: "Warning: Git remote 'target' already exists"
Solutions:
- Enter alternate name when prompted
- Remove existing remote:
git remote remove target - Use custom name:
twin --git-local-name other-name myserver
Problem: Git commands fail after setup
Check:
- SSH connection works:
ssh myserver - Remote directory is a git repo:
ssh myserver "cd /path && git status" - Remote URL is correct:
git remote -v
Solution:
- Remove existing remotes:
git remote remove target - Force re-setup:
twin -g --git-local-name newname myserver
Possible reasons:
- Not initial pairing (already paired) - use
-gto force - Used
-Gflag to skip - One or both directories aren't git repos
- Setup already completed (check
.twin.{remote}.json)