Overview
This guide demonstrates how to use Git to fetch updates from a remote template repository into your private repository while maintaining the separation between your changes and upstream template changes. This workflow is essential when working with repository templates, boilerplates, or when you need to periodically sync with upstream changes while keeping your own modifications intact.
Key Concepts
Remote Repositories: Git allows you to work with multiple remote repositories simultaneously. Each remote is tracked with a name (typically origin for your primary repository) and a URL pointing to the actual Git server location.
Fetch vs. Pull:
git fetchretrieves objects and references from a remote but doesn't modify your working directory or branchesgit pullperformsgit fetchfollowed bygit merge, directly integrating changes into your current branch
Template Pattern: This workflow creates a template remote that serves as a source for updates while keeping your own repository as the primary push destination, preventing accidental overwrites of template changes.
Detailed Workflow
Check remotes
First, verify your current remote configuration. This lists all configured remotes with their fetch and push URLs.
1git remote -vExpected Output:
origin https://github.com/your-username/your-private-repo.git (fetch)
origin https://github.com/your-username/your-private-repo.git (push)
The -v flag shows verbose output, displaying both fetch and push URLs for each remote. If you only see origin, you'll need to add the template remote in the next step.
Useful Additional Commands:
1# Show detailed information about a specific remote2git remote show origin3
4# List remotes without URLs5git remoteAdd remote template repository
Register the template repository as a new remote. This creates a tracking connection to the upstream template without overwriting your origin configuration.
1git remote add template https://github.com/original-author/template-repo.gitBreaking Down the Command:
git remote add- Creates a new remote connectiontemplate- The name/alias for this remote (can be any name, buttemplateis conventional)- URL - The HTTPS or SSH URL of the template repository
Alternative with SSH (requires SSH key setup):
1git remote add template [email protected]:original-author/template-repo.gitPost-Addition Verification:
1git remote -vShould now output:
origin https://github.com/your-username/your-private-repo.git (fetch)
origin https://github.com/your-username/your-private-repo.git (push)
template https://github.com/original-author/template-repo.git (fetch)
template https://github.com/original-author/template-repo.git (push)
Configure the Template Remote to Be Fetch-Only
This security configuration prevents accidental pushes to the template repository. By setting the push URL to no-push, Git will refuse any push attempts to this remote, protecting the template repository from unauthorized modifications.
1git remote set-url --push template no-pushTechnical Explanation:
git remote set-url- Modifies the URL configuration for a remote--push- Specifically sets the push URL (separate from fetch URL)no-push- A special value that prevents pushing to this remote
Verification:
1git remote -vNow the output shows asymmetric URLs:
origin https://github.com/your-username/your-private-repo.git (fetch)
origin https://github.com/your-username/your-private-repo.git (push)
template https://github.com/original-author/template-repo.git (fetch)
template no-push (push)
What Happens if You Attempt to Push:
1git push template main2# Error: permission denied to push to 'template'This intentional restriction ensures the template repository remains unmodified and prevents accidental contamination of upstream templates.
Fetch Updates from the Template
Download all objects and references from the template repository into your local repository. This operation is safe—it doesn't modify your working directory or current branches.
1git fetch templateWhat Gets Downloaded:
- All commits, tags, and branches from the template repository
- Git objects stored in
.git/objects/directory - References stored in
.git/refs/remotes/template/directory
Sample Output:
remote: Enumerating objects: 45, done.
remote: Counting objects: 100% (45/45), done.
remote: Compressing objects: 100% (20/20), done.
Receiving objects: 100% (45/45), 12.34 KiB | 6.17 MiB/s
From https://github.com/original-author/template-repo.git
* [new branch] main -> template/main
* [new branch] develop -> template/develop
Inspect Fetched References:
1# List all branches from template remote2git branch -r | grep template3
4# View commits in template/main5git log template/main --oneline -n 56
7# See differences between template and your main8git diff main template/main --statAdvanced Fetch Operations:
1# Fetch specific branch only2git fetch template main3
4# Fetch with pruning (remove deleted remote branches)5git fetch template --prune6
7# Fetch with depth (shallow clone for large repos)8git fetch template --depth=1Push to Your Private Repository
After fetching updates, push your current branch state to your private repository. This ensures your origin repository stays synchronized with your local work.
1git push origin mainCommand Details:
git push- Upload objects and references to a remote repositoryorigin- The destination remote (your private repository)main- The branch to push
Common Push Scenarios:
1# Push with upstream tracking (recommended for first push)2git push -u origin main3
4# Push all local branches to origin5git push origin --all6
7# Push with tags8git push origin main --tags9
10# Force push (use cautiously—overwrites remote history)11git push origin main --forcePre-Push Safety Checks:
1# Verify what will be pushed without actually pushing2git push origin main --dry-run3
4# Check current branch status5git status6
7# See commits to be pushed8git log origin/main..main --onelineUnderstanding Push Rejection: If push is rejected with:
! [rejected] main -> main (fetch first)
This means the remote has changes you don't have locally. Resolve with:
1git fetch origin2git merge origin/main3# Resolve any conflicts if needed4git push origin mainMerge template updates
Integrate changes from the template repository into your current branch using a merge operation. This combines the template changes with your existing work while preserving commit history.
1git merge template/mainMerge Behavior:
- Creates a new merge commit combining template/main and your current branch
- Preserves complete history of both branches
- Your commits and template commits remain distinct in the history
Handling Merge Conflicts:
When merging template updates, conflicts can occur if both you and template authors modified the same files. Git will mark conflicts:
1# View conflict status2git status3
4# See conflicts in detail5git diff --name-only --diff-filter=UConflict Resolution Example:
1# Manually edit conflicted files, then:2git add resolved-file.ts3git commit -m "Merge template/main: resolve conflicts"Alternative: Rebase Instead of Merge:
1# Creates linear history (template changes applied first, then your changes)2git rebase template/main3
4# If conflicts occur, after resolving:5git add .6git rebase --continueCompare Before Merging:
1# Preview what changes will be merged2git diff main template/main3
4# Show merge base (common ancestor)5git merge-base main template/main6
7# See commit statistics8git log main..template/main --oneline --statComplete Workflow Example
Here's a typical workflow session for syncing with template updates:
1# 1. Check current status2git status3git remote -v4
5# 2. Fetch latest template updates6git fetch template7
8# 3. Preview changes9git log main..template/main --oneline10git diff main template/main --stat11
12# 4. Create a feature branch for template integration (optional but recommended)13git checkout -b merge/template-update14git merge template/main15
16# 5. If no conflicts, switch back to main17git checkout main18git merge merge/template-update19
20# 6. Push to private repository21git push origin main22
23# 7. Clean up24git branch -d merge/template-updateTroubleshooting
Remote Doesn't Exist
1# If you get "fatal: 'template' does not appear to be a 'git' repository"2# Re-run the remote add command with correct URL3git remote add template https://github.com/original-author/template-repo.gitConnection Issues
1# Test remote connectivity2git remote update template --prune3
4# If SSH fails, try HTTPS URL5git remote set-url template https://github.com/original-author/template-repo.gitMerge Conflicts Resolution
1# Abort merge if needed2git merge --abort3
4# View conflicts in editor5git diff6
7# Accept all template changes8git checkout --theirs .9git add .10
11# Accept all your changes (not recommended)12git checkout --ours .13git add .Best Practices
- Fetch Regularly: Keep your template remote updated to catch changes early
- Review Before Merging: Always inspect template changes with
git diffbefore merging - Use Feature Branches: Merge template updates on a separate branch to isolate changes
- Test After Merge: Run your test suite after merging template updates
- Maintain Fetch-Only Configuration: Keep the
no-pushrestriction to prevent accidental modifications - Document Custom Changes: Keep track of which template files you've customized locally