Top Tags

Fetch remote repository template to private repository

A guide to fetching a remote repository template into your private repository using Git commands.

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 fetch retrieves objects and references from a remote but doesn't modify your working directory or branches
  • git pull performs git fetch followed by git 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.

bash
1git remote -v

Expected 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:

bash
1# Show detailed information about a specific remote
2git remote show origin
3
4# List remotes without URLs
5git remote

Add 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.

bash
1git remote add template https://github.com/original-author/template-repo.git

Breaking Down the Command:

  • git remote add - Creates a new remote connection
  • template - The name/alias for this remote (can be any name, but template is conventional)
  • URL - The HTTPS or SSH URL of the template repository

Alternative with SSH (requires SSH key setup):

bash
1git remote add template [email protected]:original-author/template-repo.git

Post-Addition Verification:

bash
1git remote -v

Should 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.

bash
1git remote set-url --push template no-push

Technical 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:

bash
1git remote -v

Now 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:

bash
1git push template main
2# 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.

bash
1git fetch template

What 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:

bash
1# List all branches from template remote
2git branch -r | grep template
3
4# View commits in template/main
5git log template/main --oneline -n 5
6
7# See differences between template and your main
8git diff main template/main --stat

Advanced Fetch Operations:

bash
1# Fetch specific branch only
2git fetch template main
3
4# Fetch with pruning (remove deleted remote branches)
5git fetch template --prune
6
7# Fetch with depth (shallow clone for large repos)
8git fetch template --depth=1

Push 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.

bash
1git push origin main

Command Details:

  • git push - Upload objects and references to a remote repository
  • origin - The destination remote (your private repository)
  • main - The branch to push

Common Push Scenarios:

bash
1# Push with upstream tracking (recommended for first push)
2git push -u origin main
3
4# Push all local branches to origin
5git push origin --all
6
7# Push with tags
8git push origin main --tags
9
10# Force push (use cautiously—overwrites remote history)
11git push origin main --force

Pre-Push Safety Checks:

bash
1# Verify what will be pushed without actually pushing
2git push origin main --dry-run
3
4# Check current branch status
5git status
6
7# See commits to be pushed
8git log origin/main..main --oneline

Understanding 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:

bash
1git fetch origin
2git merge origin/main
3# Resolve any conflicts if needed
4git push origin main

Merge 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.

bash
1git merge template/main

Merge 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:

bash
1# View conflict status
2git status
3
4# See conflicts in detail
5git diff --name-only --diff-filter=U

Conflict Resolution Example:

bash
1# Manually edit conflicted files, then:
2git add resolved-file.ts
3git commit -m "Merge template/main: resolve conflicts"

Alternative: Rebase Instead of Merge:

bash
1# Creates linear history (template changes applied first, then your changes)
2git rebase template/main
3
4# If conflicts occur, after resolving:
5git add .
6git rebase --continue

Compare Before Merging:

bash
1# Preview what changes will be merged
2git diff main template/main
3
4# Show merge base (common ancestor)
5git merge-base main template/main
6
7# See commit statistics
8git log main..template/main --oneline --stat

Complete Workflow Example

Here's a typical workflow session for syncing with template updates:

bash
1# 1. Check current status
2git status
3git remote -v
4
5# 2. Fetch latest template updates
6git fetch template
7
8# 3. Preview changes
9git log main..template/main --oneline
10git diff main template/main --stat
11
12# 4. Create a feature branch for template integration (optional but recommended)
13git checkout -b merge/template-update
14git merge template/main
15
16# 5. If no conflicts, switch back to main
17git checkout main
18git merge merge/template-update
19
20# 6. Push to private repository
21git push origin main
22
23# 7. Clean up
24git branch -d merge/template-update

Troubleshooting

Remote Doesn't Exist

bash
1# If you get "fatal: 'template' does not appear to be a 'git' repository"
2# Re-run the remote add command with correct URL
3git remote add template https://github.com/original-author/template-repo.git

Connection Issues

bash
1# Test remote connectivity
2git remote update template --prune
3
4# If SSH fails, try HTTPS URL
5git remote set-url template https://github.com/original-author/template-repo.git

Merge Conflicts Resolution

bash
1# Abort merge if needed
2git merge --abort
3
4# View conflicts in editor
5git diff
6
7# Accept all template changes
8git checkout --theirs .
9git add .
10
11# Accept all your changes (not recommended)
12git checkout --ours .
13git add .

Best Practices

  1. Fetch Regularly: Keep your template remote updated to catch changes early
  2. Review Before Merging: Always inspect template changes with git diff before merging
  3. Use Feature Branches: Merge template updates on a separate branch to isolate changes
  4. Test After Merge: Run your test suite after merging template updates
  5. Maintain Fetch-Only Configuration: Keep the no-push restriction to prevent accidental modifications
  6. Document Custom Changes: Keep track of which template files you've customized locally