Complete "Lesson 3: Branches and Merging" first to unlock this lesson.Go to previous lesson

Introduction

A GitHub remote is a named connection between a local Git repository and a repository hosted on GitHub. The local repository contains your files, commits, branches, and configuration. The remote repository stores another copy of the history so that you can back up work, collaborate, and share changes with other developers. Git does not automatically synchronize these copies; you choose when to send or receive commits.

The most common remote name is origin. This name is only a local label, not a special server built into Git. The remote URL tells Git where the GitHub repository is located, while a remote-tracking branch such as origin/main records the last remote branch state known to your local repository. Understanding this distinction prevents a common mistake: assuming that origin/main is the same object as your current local main branch.

This lesson covers the complete synchronization cycle. You will connect an existing local repository to GitHub, push commits, retrieve remote history with fetch, and integrate remote changes with pull. The examples use the main branch and assume that the GitHub repository is empty when the connection is first created.

Flowchart showing a local repository with main, a GitHub repository with main, origin as the named connection, push sending commits from local to GitHub, fetch downloading history without changing files, and pull combining fetch with integration

Connecting a Local Repository

Start with a repository that already has at least one local commit. If you are starting from an ordinary project directory, initialize Git, stage a file, and create the first commit. The command output may differ slightly between Git versions, but each command should complete without an error.

bash
git init
git add README.md
git commit -m 'Create initial project files'
git branch -M main

Create a new repository on GitHub and choose an empty repository when your local project already contains its own history. Copy its HTTPS or SSH URL, then add it as origin. Replace the example URL with the actual URL for your repository.

bash
git remote add origin https://github.com/ACCOUNT/PROJECT.git
git remote -v

The first command stores the remote configuration. The second command should display fetch and push URLs for origin. If Git reports that origin already exists, do not add a second remote with the same name. Inspect the current configuration with git remote -v, or update the URL with the following command when the existing URL is wrong.

bash
git remote set-url origin https://github.com/ACCOUNT/PROJECT.git

Pushing Local Commits

Push sends commits from a local branch to a branch on the remote repository. The first push usually includes the upstream option so that Git remembers the relationship between local main and origin/main. After this relationship is configured, later pushes can usually use the shorter command.

bash
git push -u origin main
git push

The first command asks Git to send the commits reachable from local main that are not yet present on origin/main. The option -u records origin/main as the upstream branch for main. A successful push normally reports that the new branch was created or that the branch was updated. GitHub then shows the files and commit history from the pushed branch.

A push is rejected when the remote branch contains commits that your local branch does not contain. This often happens when the GitHub repository was initialized with a README, license, or other file before you pushed. It can also happen when another contributor pushed first. Treat the rejection as a request to synchronize histories, not as permission to overwrite the remote immediately. Retrieve the remote commits, inspect the resulting history, and integrate them before pushing again.

bash
git pull --rebase origin main
git push

Rebase replays your local commits after the updated remote history and can keep a linear history. If conflicts occur, Git pauses and marks the affected files. Resolve the conflict, stage the resolved files, continue the rebase, and then push. Do not use force push casually, because it can remove commits that other people depend on.

Fetching and Pulling Changes

Fetch downloads new commits, branch references, and other remote information without changing the files currently checked out. This makes fetch useful when you want to inspect incoming work before deciding how to integrate it. It updates the remote-tracking reference origin/main, while your local main branch and working files remain unchanged.

bash
git fetch origin
git log --oneline main..origin/main
git diff main origin/main

If the log command prints commits, those commits exist on origin/main but not on local main. The diff command shows file-level differences between the two references. If both commands produce no relevant output, your local knowledge of the remote is aligned with your local branch, although another remote push could happen immediately afterward.

Pull is a higher-level operation. In its usual form, it fetches from the selected remote and then integrates the fetched branch into the current branch. The integration may use a merge or a rebase depending on configuration and command options. The following command updates the current main branch from origin/main.

bash
git switch main
git pull origin main

A merge may create a merge commit when both local and remote branches have new commits. A rebase moves local commits so they follow the fetched remote commits. Both approaches can be valid, but a team should agree on its history policy. The important operational rule is to inspect the current branch before pulling and to read Git's conflict instructions when automatic integration cannot complete.

Keeping Histories Aligned

A reliable workflow begins by checking status and branch information before making a synchronization decision. The status command tells you whether local files are modified, staged, or clean. The branch command shows the current branch and its upstream relationship. These checks help you avoid pulling into the wrong branch or losing track of uncommitted work.

bash
git status
git branch -vv
git fetch origin
git log --oneline --decorate --graph --all -n 12

If you have uncommitted changes, decide whether to commit them, stash them, or discard them before integrating remote work. Pulling with unrelated local modifications can be blocked or can make conflict resolution harder. A small focused commit is often the clearest choice when the work is ready to be recorded.

When local main and origin/main have both advanced, the branches have diverged. Fetch first, then choose an integration strategy that matches the project policy. A merge preserves the exact branching event. A rebase creates a more linear local history but rewrites the commit identities of the rebased local commits. After integration, run the project tests or other verification commands, inspect the final status, and push the resulting commits.

Authentication is separate from Git's history logic. With an HTTPS remote, GitHub may require a credential manager or a personal access token rather than an account password. With an SSH remote, the correct public key must be registered with GitHub and the remote URL must use the SSH format. An authentication error means Git could not prove your identity; it does not normally mean that the branch histories conflict.

Common Errors and Summary

The error fatal: not a git repository means the command was run outside the intended repository or a parent directory without Git metadata. Change to the project directory and verify that it contains the repository metadata. The error remote origin already exists means a remote with that name is already configured. Inspect it before deciding whether to change its URL.

The message rejected because the remote contains work that you do not have means the remote branch has commits missing locally. Fetch or pull, inspect conflicts, integrate the histories, and push again. The message src refspec main does not match any commonly means that a local main branch does not exist or that the repository has no commit yet. Check the branch name with git branch and create the initial commit before pushing.

The essential model is simple. Commit records work locally. Push sends local commits to GitHub. Fetch downloads remote history and updates remote-tracking references without changing the checked-out files. Pull fetches and then integrates remote work into the current branch. Regular status checks, explicit branch names, and careful conflict handling keep the local and remote histories understandable and aligned.

Lesson practice

Lesson Checkpoint

Review what you learned and get feedback on your work.

0/1
Answered · 0/1