---
title: "06 — Repo Hosting: The Social and Automation Shell Around Git"
uid: repo-hosting-services
tags: ["github", "collaboration", "gitlab", "tooling", "version-control", "roadmap:frontend"]
excerpt: "Git is the engine; GitHub and GitLab are the social and automation shell around it. See those two layers separately and the hosts stop looking arbitrary."
date: 2026-08-12T18:35:12+0000
source: https://www.aveshina.my.id/en/blog/repo-hosting-services
---

I quietly confused repository hosting with Git itself, which made every host's differences feel arbitrary. The untangling: **Git is the engine, and a repo host is the social and automation shell wrapped around it.** Git does one job — track history as a graph of commits. The host takes that local graph and turns it into shared, reviewable, CI-able project infrastructure [1]. Once I could see those two layers separately, the differences between GitHub and GitLab stopped feeling arbitrary and started looking like different bets on which shell matters more.

Here's the picture I keep in my head — the engine on the left, the shell on the right:

```figure
<svg viewBox="0 0 740 300" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="Git as the engine on the left, repo host as the collaboration shell on the right. Left box: Git engine — commits and branches as a tracked graph of history, works fully offline. A single arrow labelled git push / git fetch crosses the middle. Right box: the hosting shell, split into three panes — Pull requests and code review, Issues and project tracking, CI/CD and automation. Caption: the host adds collaboration and automation on top of the same Git.">
  <defs>
    <marker id="rarrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">

    <!-- Git engine -->
    <rect x="30" y="60" width="220" height="180" rx="10" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="140" y="86" font-size="13" font-weight="700" fill="#1e1b4b" text-anchor="middle">Git — the engine</text>
    <text x="140" y="104" font-size="10.5" fill="#475569" text-anchor="middle">tracks history as a graph</text>

    <!-- mini commit graph -->
    <g stroke="#6366f1" stroke-width="1.5" fill="#fff">
      <circle cx="70" cy="150" r="8"/>
      <circle cx="110" cy="150" r="8"/>
      <circle cx="110" cy="186" r="8"/>
      <circle cx="150" cy="150" r="8"/>
      <circle cx="190" cy="150" r="8"/>
      <line x1="78" y1="150" x2="102" y2="150"/>
      <line x1="118" y1="150" x2="142" y2="150"/>
      <line x1="158" y1="150" x2="182" y2="150"/>
      <line x1="110" y1="158" x2="110" y2="178"/>
    </g>
    <text x="140" y="218" font-size="10" fill="#475569" text-anchor="middle">commits &amp; branches — works offline</text>

    <!-- the bridge -->
    <path d="M255,150 L405,150" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#rarrow)"/>
    <text x="330" y="143" font-size="10" fill="#475569" text-anchor="middle">git push / git fetch</text>
    <text x="330" y="165" font-size="9.5" fill="#94a3b8" text-anchor="middle" font-style="italic">the only thing that crosses</text>

    <!-- hosting shell -->
    <rect x="410" y="60" width="300" height="180" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="560" y="86" font-size="13" font-weight="700" fill="#052e16" text-anchor="middle">Repo host — the shell</text>
    <text x="560" y="104" font-size="10.5" fill="#475569" text-anchor="middle">collaboration + automation layer</text>

    <!-- three panes -->
    <rect x="426" y="120" width="268" height="32" rx="6" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.2"/>
    <text x="560" y="141" font-size="11" font-weight="700" fill="#422006" text-anchor="middle">Pull requests · code review</text>

    <rect x="426" y="158" width="268" height="32" rx="6" fill="#fce7f3" stroke="#db2777" stroke-width="1.2"/>
    <text x="560" y="179" font-size="11" font-weight="700" fill="#500724" text-anchor="middle">Issues · project tracking</text>

    <rect x="426" y="196" width="268" height="32" rx="6" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.2"/>
    <text x="560" y="217" font-size="11" font-weight="700" fill="#1e1b4b" text-anchor="middle">CI/CD · automation</text>

    <text x="370" y="272" font-size="10.5" fill="#64748b" text-anchor="middle" font-style="italic">the host adds the shell — Git underneath is unchanged</text>
  </g>
</svg>
```

## What the host adds that Git alone doesn't

Git, on its own, is a local concern. I can commit, branch, and merge forever on my laptop and nobody else ever sees it. The thing that turns that private history into a team artifact is a **remote** — another Git repository, reachable over the network, that I push to and fetch from. A repo host is, at its core, *one of those remotes that other people also push to and fetch from*, plus a web UI and a set of collaboration tools built on top [1].

The shell layer is where most of what I actually recognize as "working on a project" lives:

- **Pull / merge requests** — a proposed change, scoped to a branch, with diff view, line-by-line review, required approvals. This is not a Git concept; it's a host concept. Git merges branches. The host stages the conversation around *whether* to merge them.
- **Issues and project boards** — a shared to-do list and tracker tied to the repository.
- **Forks and permissions** — a model for who can push directly and who works through a copy.
- **CI/CD pipelines** — automation that runs tests, builds, and deploys on events like a push or a PR, defined in a file committed to the repo itself.
- **Webhooks and integrations** — the host notifies other services when things happen.

The mental shift: none of that is Git. It's a product layer that speaks Git underneath. Which is why two hosts can share the exact same engine and still feel completely different — they're different shells.

## GitHub: the network

GitHub is the largest repository host and the de facto home of open source [2]. Microsoft acquired it in 2018 [2]. The thing I had to understand about GitHub is that its dominant feature isn't any single tool — it's **network effect**. When a library lives on GitHub, its issues, its pull requests, its contributors, its dependabot alerts, its Actions marketplace, and its visibility in search all compound. For an open-source project, being somewhere a contributor can find it and file a PR in under a minute is worth more than any feature checkbox.

GitHub's automation is **GitHub Actions** — workflow YAML files that run jobs on runners, triggered by repo events [3]. To be clear: GitHub is end-to-end today. Actions for CI/CD, Packages for registries, Projects for issue tracking, Codespaces for dev environments, and a full security stack (CodeQL, secret scanning, Dependabot) are all first-class [2]. The honest caveat is timing — these arrived later, layered onto the social graph. The network was the product first; the toolchain grew out of it.

## GitLab: the platform

GitLab takes a different bet — not because GitHub lacks the toolchain (it doesn't anymore), but because GitLab built **the whole delivery pipeline as one integrated product from day one**, not assembled in stages [4]. Its signature is built-in CI/CD — defined by a single .gitlab-ci.yml at the repo root, run on GitLab Runners — and it predates and arguably out-matures GitHub Actions [5]. Issue tracking, merge requests, container registry, package registry, security scanning, environments, and deployments were all there from the start, in one application.

The other thing GitLab is known for is being **self-hostable**. The entire platform is open-core — I can run it on my own infrastructure, behind my own firewall, with the same UI as the SaaS version [4]. For teams that can't or won't put their code on someone else's cloud (regulated industries, on-prem mandates, air-gapped networks), that's the deciding factor, not a preference.

## The comparison I actually use

The model collapses the choice into one trade-off:

Neither is "better." Both are end-to-end these days; the real fork is *cloud-first network* versus *self-hostable platform*. For an open-source side project where I want strangers to find and contribute to my work, GitHub is the default because that's where the contributors are. For a team that must run the whole platform on its own hardware — regulated, on-prem, air-gapped — GitLab is the more coherent shape. Bitbucket exists in this same layer too — Atlassian's entry, tightly bound to Jira — but for frontend work the GitHub/GitLab split is what I actually encounter.

## How I use this

The habit these notes left me with is a single separation: when something breaks or behaves oddly, I ask *is this Git, or is this the host?* A rebase conflict, a detached HEAD, a botched merge — that's the engine, and the answer is the same on any host. A missing CI run, a permissions error on a branch, a PR that won't auto-merge, a stale webhook — that's the shell, and the answer is product-specific. Naming which layer I'm actually in saves me from grepping the wrong docs every time.

## References

[1] Git, "Git - Distributed Git - Distributed Workflows," Git Documentation. [Online]. Available: [https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows](https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows)

[2] GitHub, "About GitHub," GitHub Docs. [Online]. Available: [https://docs.github.com/en/get-started/quickstart/hello-world](https://docs.github.com/en/get-started/quickstart/hello-world)

[3] GitHub, "Understanding GitHub Actions," GitHub Docs. [Online]. Available: [https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions)

[4] GitLab, "What is GitLab?," GitLab Documentation. [Online]. Available: [https://about.gitlab.com/what-is-gitlab/](https://about.gitlab.com/what-is-gitlab/)

[5] GitLab, "GitLab CI/CD," GitLab Documentation. [Online]. Available: [https://docs.gitlab.com/ee/ci/](https://docs.gitlab.com/ee/ci/)

```quiz
Q: A pull request is fundamentally a feature of…
- Git itself — it's a core Git command
- the repository host — a collaboration layer built on top of Git
correct: 1
explain: Git only knows branches and merges. The pull request — the staged conversation around whether to merge — is a host concept. `git merge` exists; `git pull-request` does not.

Q: What is the defining strength of GitHub?
- the largest open-source network — where contributors already are
- built-in, mature CI/CD that predates every competitor
- the ability to self-host on my own infrastructure
correct: 0
explain: GitHub's dominant advantage is network effect: it's the default home of open source, so contributors, issues, and tooling compound there. Mature built-in CI/CD and self-hosting are GitLab's bets, not GitHub's.

Q: A team must run its entire DevOps platform on its own hardware, behind a firewall. The most coherent choice is…
- GitHub (cloud only)
- GitLab (self-hosted, open-core)
correct: 1
explain: GitLab is open-core and fully self-hostable — the whole platform runs on your own infra. GitHub's product is cloud-first; GitHub Enterprise is dedicated infrastructure but still vendor-run.

Q: On my laptop I can commit, branch, and merge with no internet connection. This is possible because…
- the repo host caches everything for offline use
- Git is a local engine that tracks history as a graph; the host is only needed to share it
correct: 1
explain: Git works fully offline — the commit graph lives on your machine. The host only enters the picture when you push or fetch, i.e. when you want to share that history with others.

Q: My CI pipeline didn't run after a push. Which layer is the problem most likely in?
- Git — the engine
- the host — the shell (workflow config, runners, webhooks)
correct: 1
explain: CI/CD is part of the hosting shell, defined by a workflow file and triggered by host events. A missing run is almost always a host-layer issue — workflow syntax, runner availability, or a webhook — not a Git engine problem.
```
