Git Remotes
Remote repository management and collaboration.
Remote Fundamentals
# LIST REMOTES
git remote # Names only
git remote -v # With URLs
git remote show origin # Detailed info
# ADD REMOTE
git remote add origin git@github.com:user/repo.git
git remote add upstream git@github.com:original/repo.git
git remote add gitlab git@gitlab.com:user/repo.git
# CHANGE REMOTE URL
git remote set-url origin git@github.com:newuser/repo.git
git remote set-url --push origin git@other-host.com:user/repo.git # Push to different URL
# RENAME REMOTE
git remote rename origin old-origin
git remote rename gitlab origin
# REMOVE REMOTE
git remote remove gitlab
git remote rm gitlab # Short form
# REMOTE CONVENTIONS
# origin = your fork or primary remote
# upstream = original repo you forked from
# gitlab = mirror on GitLab
# backup = backup location
# SHOW REMOTE DETAILS
git remote show origin
# Shows:
# - Fetch/push URLs
# - HEAD branch
# - Remote branches
# - Local branches tracking remote
# - Stale branches
Fetch Patterns
# BASIC FETCH
git fetch # Fetch from origin
git fetch origin # Same, explicit
git fetch --all # Fetch from ALL remotes
# FETCH SPECIFIC
git fetch origin main # Only main branch
git fetch origin feature # Specific branch
git fetch origin refs/pull/123/head:pr-123 # GitHub PR
# FETCH WITH PRUNE
git fetch --prune # Remove stale remote-tracking branches
git fetch -p # Short form
git fetch --prune-tags # Also prune tags
# FETCH TAGS
git fetch --tags # Fetch all tags
git fetch origin --tags # Tags from specific remote
# FETCH DRY RUN
git fetch --dry-run # Show what would be fetched
# FETCH VS PULL
# fetch: download changes, don't merge
# pull: fetch + merge (or rebase)
# PREFER fetch + manual merge for control
# AFTER FETCH
git log origin/main..HEAD # Your commits not on remote
git log HEAD..origin/main # Remote commits you don't have
git diff origin/main # Your changes vs remote
# CONFIGURE FETCH DEFAULTS
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
# Fetch all branches by default
Pull Patterns
# BASIC PULL
git pull # Pull from tracking branch
git pull origin main # Pull specific branch
# PULL WITH REBASE
git pull --rebase # Rebase instead of merge
git pull --rebase=merges # Preserve local merges
git pull -r # Short for --rebase
# MAKE REBASE DEFAULT
git config pull.rebase true # For this repo
git config --global pull.rebase true # Global default
# PULL STRATEGIES
git pull --ff-only # Only if fast-forward possible
git pull --no-ff # Always create merge commit
# PULL SPECIFIC BRANCH
git pull origin feature # Pull feature into current
git pull origin feature:local-feature # Pull into specific local branch
# PULL ALL REMOTES
git pull --all # Pull from all remotes
# HANDLE PULL CONFLICTS
git pull
# CONFLICT...
# Fix conflicts, then:
git add resolved-files
git commit # Complete merge
# OR if rebasing:
git pull --rebase
# CONFLICT...
git add resolved-files
git rebase --continue
# SAFE PULL WORKFLOW
git fetch origin
git log HEAD..origin/main # Review incoming changes
git merge origin/main # Controlled merge
# OR: git rebase origin/main
To reset your local branch to exactly match the remote (discard all local changes), see Rewriting: Reset Operations — git fetch origin && git reset --hard origin/main.
|
Push Patterns
# BASIC PUSH
git push # Push to tracking branch
git push origin main # Push main to origin
# PUSH WITH UPSTREAM
git push -u origin main # Push and set upstream
git push --set-upstream origin main # Same, verbose
# After this, just "git push" works
# PUSH ALL BRANCHES
git push --all # All local branches
git push origin --all # To specific remote
# PUSH TAGS
git push --tags # All tags
git push origin v1.0.0 # Specific tag
git push --follow-tags # Push commits + related tags
# DELETE REMOTE BRANCH
git push origin --delete feature # Delete remote branch
git push origin :feature # Same, older syntax
# FORCE PUSH (careful!)
git push --force # Overwrite remote (DANGEROUS)
git push --force-with-lease # Safe force (fails if remote changed)
# ALWAYS use --force-with-lease over --force
# PUSH SPECIFIC COMMIT
git push origin abc1234:main # Push commit to remote branch
# PUSH TO DIFFERENT BRANCH
git push origin local-branch:remote-branch
# DRY RUN
git push --dry-run # Show what would be pushed
git push -n # Short form
# PUSH ALL REMOTES
for remote in $(git remote); do
git push "$remote" main
done
Multi-Remote Workflows
# SETUP MULTI-REMOTE
git remote add origin git@github.com:EvanusModestus/repo.git
git remote add gitlab git@gitlab.com:EvanusModestus/repo.git
git remote add backup git@backup-server.com:repo.git
# VIEW ALL REMOTES
git remote -v
# origin git@github.com:EvanusModestus/repo.git (fetch)
# origin git@github.com:EvanusModestus/repo.git (push)
# gitlab git@gitlab.com:EvanusModestus/repo.git (fetch)
# gitlab git@gitlab.com:EvanusModestus/repo.git (push)
# PUSH TO ALL REMOTES
git push origin main
git push gitlab main
# OR:
for remote in origin gitlab backup; do
git push "$remote" main
done
# CONFIGURE PUSH TO MULTIPLE URLS
# Add multiple push URLs to single remote:
git remote set-url --add --push origin git@github.com:user/repo.git
git remote set-url --add --push origin git@gitlab.com:user/repo.git
# Now "git push origin" pushes to both!
# FETCH FROM ALL
git fetch --all # All remotes
git remote update # Same
# COMPARE REMOTES
git log origin/main..gitlab/main --oneline
# Commits on GitLab not on GitHub
# FORK WORKFLOW (upstream)
git remote add upstream git@github.com:original/repo.git
git fetch upstream
git merge upstream/main # Get changes from original
git push origin main # Push to your fork
# KEEP FORK IN SYNC
git fetch upstream
git checkout main
git rebase upstream/main
git push origin main
# DIFFERENT FETCH/PUSH REMOTES
git remote set-url origin git@github.com:upstream/repo.git # Fetch from upstream
git remote set-url --push origin git@github.com:myfork/repo.git # Push to fork
Infrastructure Repository Remotes
# DOMUS-* REPO REMOTE SETUP
# Most repos push to both GitHub and GitLab
# VIEW REMOTES FOR REPO
git -C ~/atelier/_bibliotheca/domus-infra-ops remote -v
# origin git@github.com:EvanusModestus/domus-infra-ops.git (fetch)
# origin git@github.com:EvanusModestus/domus-infra-ops.git (push)
# gitlab git@gitlab.com:EvanusModestus/domus-infra-ops.git (fetch)
# gitlab git@gitlab.com:EvanusModestus/domus-infra-ops.git (push)
# PUSH TO ALL REMOTES (single repo)
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket git push origin main
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket git push gitlab main
# PUSH ALL DOMUS-* REPOS TO ALL REMOTES
for repo in ~/atelier/_bibliotheca/domus-*/; do
name=$(basename "$repo")
echo "=== $name ==="
for remote in origin gitlab; do
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket \
git -C "$repo" push "$remote" main 2>/dev/null || echo " $remote: skipped/failed"
done
done
# CHECK SYNC STATUS ACROSS REMOTES
for repo in domus-infra-ops domus-captures domus-ise-linux; do
echo "=== $repo ==="
git -C ~/atelier/_bibliotheca/$repo fetch --all -q
origin=$(git -C ~/atelier/_bibliotheca/$repo rev-parse origin/main)
gitlab=$(git -C ~/atelier/_bibliotheca/$repo rev-parse gitlab/main 2>/dev/null || echo "N/A")
local=$(git -C ~/atelier/_bibliotheca/$repo rev-parse main)
echo " local: ${local:0:7}"
echo " origin: ${origin:0:7}"
echo " gitlab: ${gitlab:0:7}"
done
# ADD REMOTE TO EXISTING REPO
cd ~/atelier/_bibliotheca/domus-new-repo
git remote add origin git@github.com:EvanusModestus/domus-new-repo.git
git remote add gitlab git@gitlab.com:EvanusModestus/domus-new-repo.git
git push -u origin main
git push -u gitlab main
# PRUNE STALE REMOTES ACROSS REPOS
for repo in ~/atelier/_bibliotheca/domus-*/; do
git -C "$repo" fetch --all --prune
done
# VERIFY SSH AUTH BEFORE PUSH
ssh -T git@github.com # Test GitHub
ssh -T git@gitlab.com # Test GitLab
SSH Remote Configuration
# SSH VS HTTPS
# SSH: git@github.com:user/repo.git
# HTTPS: https://github.com/user/repo.git
# CONVERT HTTPS TO SSH
git remote set-url origin git@github.com:user/repo.git
# CONVERT SSH TO HTTPS
git remote set-url origin https://github.com/user/repo.git
# SSH CONFIG FOR MULTIPLE GITHUB ACCOUNTS
# ~/.ssh/config:
# Host github-personal
# HostName github.com
# User git
# IdentityFile ~/.ssh/id_ed25519_personal
#
# Host github-work
# HostName github.com
# User git
# IdentityFile ~/.ssh/id_ed25519_work
# USE WITH REMOTES
git remote add personal git@github-personal:personal-user/repo.git
git remote add work git@github-work:work-org/repo.git
# VAULT SSH CA INTEGRATION
# Sign certificate before pushing:
~/.local/bin/vault-ssh-sign
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket git push origin main
# TEST SSH CONNECTION
ssh -vT git@github.com # Verbose test
ssh -T git@gitlab.com # GitLab test
# SPECIFY SSH KEY FOR GIT
GIT_SSH_COMMAND="ssh -i ~/.ssh/specific_key" git push
# SSH AGENT FORWARDING
# For push from remote servers
ssh -A server # Forward agent
git push origin main # Uses forwarded key
Remote Gotchas
# WRONG: Pushing without upstream
git push
# Error: no upstream branch
# CORRECT: Set upstream first
git push -u origin main
# Future pushes: just "git push"
# WRONG: Force pushing shared branches
git push --force origin main
# Overwrites others' work!
# CORRECT: Use --force-with-lease or don't force
git push --force-with-lease origin main
# OR don't force push main at all
# WRONG: Pulling with dirty working tree
git pull
# Error: Your local changes would be overwritten
# CORRECT: Stash or commit first
git stash
git pull
git stash pop
# WRONG: Fetching but not pruning
git fetch
# Stale branches accumulate forever
# CORRECT: Fetch with prune
git fetch --prune
# OR configure: git config remote.origin.prune true
# WRONG: Assuming origin is always correct
git push origin main
# origin could point anywhere!
# CORRECT: Verify remotes
git remote -v
git remote show origin
# WRONG: Pushing large files
git add big-video.mp4
git commit -m "add video"
git push
# Rejected or very slow!
# CORRECT: Use Git LFS for large files
git lfs install
git lfs track "*.mp4"
git add .gitattributes big-video.mp4
git commit -m "add video (LFS)"
git push
# WRONG: Mixing SSH and HTTPS remotes
# May have credential caching issues
# CORRECT: Use consistent protocol
git remote set-url origin git@github.com:user/repo.git
git remote set-url gitlab git@gitlab.com:user/repo.git
# WRONG: Not fetching before comparing
git log origin/main..HEAD
# May show stale data!
# CORRECT: Fetch first
git fetch origin
git log origin/main..HEAD
Quick Reference
# REMOTE MANAGEMENT
git remote -v # List remotes
git remote add name URL # Add remote
git remote set-url origin URL # Change URL
git remote remove name # Remove remote
# FETCH
git fetch # From origin
git fetch --all # All remotes
git fetch --prune # Remove stale refs
git fetch origin main # Specific branch
# PULL
git pull # Fetch + merge
git pull --rebase # Fetch + rebase
git pull origin main # From specific
# PUSH
git push # To tracking branch
git push -u origin main # Set upstream
git push --all # All branches
git push --tags # All tags
git push origin --delete branch # Delete remote branch
git push --force-with-lease # Safe force push
# COMPARISON
git log origin/main..HEAD # Local not on remote
git log HEAD..origin/main # Remote not local
git fetch && git status # See ahead/behind
# MULTI-REMOTE
git push origin main && git push gitlab main
for remote in origin gitlab; do git push "$remote" main; done
# SSH REMOTES
git remote set-url origin git@github.com:user/repo.git
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket git push
See Also
-
Rewriting —
git reset --hard origin/mainto match remote -
Tags — push/pull tags with remotes
-
Filter-Repo — force push after surgery