09. Remotes - ivomac/GitBasics GitHub Wiki
🐻 Bare Repository
- A bare git repository is one without a checked-out workdir.
- In a typical project folder, you will have:
project_name/ # 📂 Working Directory
├── .git/ # 🪣 Git Repository
│ ├── HEAD
│ ├── index
│ └── ...
│ ...
└── README.md
- 🐻 A bare git repository holds only the contents of .git:
project_name.git/ # 🪣 Bare Git Repository
├── HEAD
├── index
└── ...
- 🌐 Bare git repositories are typically used in servers which host the repository online.
- 🔄 Collaborators/users can use such repositories to synchronize changes.
🌐 Remotes
- 🌍 A remote is a reference in the local repository to a remote repository.
- 🏷️ Each remote has a unique name and a location.
- 🐻 The remote is usually a bare repository in a server, and the location is a URL.
- 📝 The most common remote name (when there is only one) is origin.
Local Repository | Repository in a remote location (origin)
|
| G ◄─ H ◄ test
| ▼
A ◄─ B ◄─ C ◄ main | A ◄─ B ◄─ C ◄ main
▲ | ▲
D ◄─ E ◄─ F ◄ feature ◄ HEAD | D ◄─ E ◄ feature
🔗 Tracking Branches
- 🏷️ Branches are local to each repository, but may be linked between repositories.
- 👉 A tracking branch is a local copy/reference of a branch in a remote.
- 📍 They show where the remote branch was the last time it was synchronized.
- 🧭 Tracking branches are named as
remote_name/branch_name
.
- 🏠
feature
refers to the local branch pointing to F.
- 🌐
origin/feature
refers to the branch in the origin repo pointing to E.
📥 Fetching
- 📡 We update the local tracking branches by fetching from a remote.
- 📥 Fetching downloads new commits from the remote repository if needed.
- 🛡️ It does not modify your local branches or your working directory.
📥 Fetch Scenario
- 🔄 In the example above, if we fetch all branches from origin:
Local Repository | Repository in a remote location (origin)
|
G ◄─ H ◄ origin/test | G ◄─ H ◄ test
▼ | ▼
A ◄─ B ◄─ C ◄ main, origin/main | A ◄─ B ◄─ C ◄ main
▲ | ▲
D ◄─ E ◄─ F ◄ feature ◄ HEAD | D ◄─ E ◄ feature
▲ |
origin/feature |
- ⚖️ Local main is in sync with origin/main.
- ⬆️ Local feature is one commit ahead of origin/feature.
- 🆕 New commits G, H, from branch test in origin are now available locally in origin/test.
- 🏠 Local branches (main, feature) remain unchanged.
- 🤝 With tracking branches, we see the local and (last seen) remote state in the local graph.
⬆️ Upstream Branch
- 🔗 The upstream branch is the default tracking branch that a local branch should sync with.
- ⛳ Commonly, you want to sync a local branch with the remote branch of the same name:
main
with origin/main
, feature
with origin/feature
.
- 🟰 The upstream branch is almost always set to the branch of the same name in the remote.
- 🤷♂️ You could always sync a local branch with any remote branch... but why?
📤 Pushing
- Pushing uploads your local commits to the remote repository.
- ⬆️ It updates a remote branch to match your local branch.
- ⚠️ Pushing can fail if the remote has changes you don't have locally.
📤 Push Scenario
Local Repository | Repository in a remote location (origin)
|
A ◄─ B ◄─ C ◄─ D ◄ main ◄ HEAD | A ◄─ B ◄─ C ◄ main
▲ |
origin/main |
Local Repository | Repository in a remote location (origin)
|
A ◄─ B ◄─ C ◄─ D ◄ main ◄ HEAD | A ◄─ B ◄─ C ◄─ D ◄ main
▲ |
origin/main |
- ✅ Remote main now includes commit D
- 🔄 Local tracking branch updated automatically
⚔️ Push Conflicts
- 🚫 Pushing fails if the remote has commits you don't have:
Local Repository | Repository in a remote location (origin)
|
A ◄─ B ◄─ C ◄─ D ◄ main ◄ HEAD | A ◄─ B ◄─ C ◄─ E ◄ main
▲ |
origin/main |
- 🔄 To properly synchronize local and remote main, we could first fetch:
Local Repository | Repository in a remote location (origin)
|
A ◄─ B ◄─ C ◄─ D ◄ main ◄ HEAD | A ◄─ B ◄─ C ◄─ E ◄ main
▲ |
E ◄ origin/main |
- ↕️ We see that main is 1 commit behind, 1 commit ahead of origin/main (⬇️1⬆️1).
- ✏️ We then rebase main on top of origin/main:
Local Repository | Repository in a remote location (origin)
|
A ◄─ B ◄─ C ◄─ E ◄─ F ◄ main ◄ HEAD | A ◄─ B ◄─ C ◄─ E ◄ main
▲ |
origin/main |
- 📝 F is the rebased D commit.
- 🟢 We can now push without conflicts:
Local Repository | Repository in a remote location (origin)
|
A ◄─ B ◄─ C ◄─ E ◄─ F ◄ main ◄ HEAD | A ◄─ B ◄─ C ◄─ E ◄─ F ◄ main
▲ |
origin/main |
🔄 Pull: Fetch + Merge
- Pulling updates the current local branch with the changes in its upstream branch.
- It combines fetching and rebasing/merging in one operation:
- 📥 First, it fetches the upstream tracking branch of the current branch (origin/main for main).
- ⬆️ If the upstream branch is ahead of the local branch, we move the local branch forward.
- This is known as fast-forward.
- 🔀 If the branches have diverged, the default is to merge local and tracking branches.
- 📝 The default can be changed to rebase local branch on top of tracking branch instead.
🔀 Merge/Pull Requests
- 🌐 Merge/Pull Requests are a feature provided by Git hosts like GitHub and GitLab.
- 🤝 Merge/Pull Requests are requests to push/merge the local changes to the remote repository.
- 👀 The changes in the request can then be reviewed before the merge is approved.
- 📥 The merging happens in the remote. Fetch/Pull after to update locally.
- 📋 They provide a structured way to discuss, review, and integrate code changes.
- 🏷️ Pull Request (GitHub) 🟰 Merge Request (GitLab/BitBucket)