28 KiB
28 KiB
# Git on the Server
## Purpose & context
- Current baseline
- You should now be able to handle most day-to-day Git tasks
- Why a remote repository is needed for collaboration
- Collaboration requires a remote Git repository
- While you *can* push/pull directly between individuals’ repositories:
- It’s discouraged (easy to confuse what others are working on)
- Collaborators need access even if your computer is offline
- Preferred approach
- Set up an *intermediate* repository that everyone can access
- Everyone pushes to / pulls from that common repository
- Running a Git server (high-level)
- Choose which protocols your server should support
- Chapter structure
- Protocol options + pros/cons
- Typical setups and how to get them running
- Hosted options (if you don’t want to self-host)
- If you don’t want to run your own server
- Skip to “Third Party Hosted Options”
- Then continue to the next chapter about distributed workflows
- What a “remote repository” usually is
- Generally a **bare repository**
- No working directory
- Used only as a collaboration point
- Bare repository in simplest terms
- Contents of your project’s `.git` directory
- And nothing else
## The Protocols (ways Git transfers data)
- Four distinct protocols
- **Local**
- **HTTP** (Smart + Dumb)
- **SSH**
- **Git** (git://)
- Selection depends on
- Authentication requirements
- Public vs private access needs
- Firewall constraints
- Ease of setup/maintenance
- Performance expectations
### Local Protocol
- Definition
- Remote repository is just another directory on the **same host**
- Typical use cases
- Team shares a filesystem (e.g., **NFS mount**)
- Less likely: everyone logs into the **same computer**
- Not ideal: all repos on one machine → catastrophic loss risk higher
- How to use (clone / add remote)
- Clone using a filesystem path
- `git clone /srv/git/project.git`
- Clone explicitly using `file://`
- `git clone file:///srv/git/project.git`
- Add as a remote to an existing project
- `git remote add local_proj /srv/git/project.git`
- Then push/pull using `local_proj` like a network remote
- Path vs `file://` behavior
- Plain path (no `file://`)
- Git tries to use **hardlinks** or directly **copies** needed files
- With `file://`
- Git uses network-style transfer processes
- Generally **less efficient**
- Why ever use `file://`?
- To get a “clean” copy (leave out extraneous refs/objects)
- Often after importing from another VCS (maintenance tasks noted in “Git Internals”)
- Recommended in this chapter
- Use the normal path (almost always faster)
- Pros
- Simple to set up
- Uses existing filesystem permissions and access
- Easy when you already have a shared filesystem
- Put a bare repo where everyone can access it
- Set read/write permissions like any shared directory
- Convenient for quick sharing from someone’s working repo
- e.g., `git pull /home/john/project` can be simpler than using a server
- Cons
- Shared filesystem access can be harder from multiple locations than network access
- Example: pushing from home may require mounting a remote disk (slow/difficult)
- Performance caveat on shared mounts
- “Local” is fast only if data access is fast
- NFS can be slower than SSH (even to same server) because SSH lets Git use local disks
- Risk of accidental repository damage
- Users have full shell access to the “remote” directory
- Nothing prevents deleting/modifying internal Git files → corruption risk
### HTTP Protocols
- Two modes
- **Dumb HTTP**
- Older (pre Git 1.6.6)
- Simple, generally read-only
- **Smart HTTP**
- Introduced in Git 1.6.6
- More capable: negotiates transfers intelligently (similar to SSH)
- Has become very popular due to usability + efficiency
#### Smart HTTP
- How it works (conceptually)
- Similar to SSH/Git protocols but runs over standard **HTTPS ports**
- Can use multiple HTTP authentication mechanisms
- Often easier than SSH key setup
- Supports username/password prompting
- Usability benefits
- Single URL can support
- Anonymous reads (like `git://`)
- Authenticated/encrypted pushes (like SSH)
- Client behavior
- If push requires auth → server prompts for username/password
- Same for reads if configured
- Example behavior (hosted services)
- For GitHub-like services
- The web URL (e.g., `https://github.com/...`) can also be used to clone/push (if authorized)
#### Dumb HTTP
- When used
- Git client falls back to Dumb HTTP if server doesn’t respond with a smart HTTP service
- Expectations
- Bare Git repository is served as static files by a web server
- Setup (read access)
- Place bare repo under HTTP document root + enable a `post-update` hook
- Example sequence
- `cd /var/www/htdocs/`
- `git clone --bare /path/to/git_project gitproject.git`
- `cd gitproject.git`
- `mv hooks/post-update.sample hooks/post-update`
- `chmod a+x hooks/post-update`
- Why the hook matters
- Default `post-update` runs `git update-server-info`
- That makes HTTP fetching/cloning work properly
- Typically triggered when someone pushes to the repo (often over SSH)
- Cloning from Dumb HTTP
- `git clone https://example.com/gitproject.git`
- Server flexibility
- Apache example uses `/var/www/htdocs`
- Any static web server works if it can serve the bare repo files
- “Git Internals” referenced for details of how the data is served
- Common deployment choice
- Usually you run either:
- Smart HTTP read/write, **or**
- Dumb HTTP read-only
- Rare to run a mix
#### HTTP Pros (focus on Smart HTTP)
- Single URL for all access types
- Server prompts only when authentication is needed
- Username/password authentication
- Avoids SSH key generation/upload steps
- Especially useful for less sophisticated users or environments where SSH is uncommon
- Performance
- Fast and efficient (comparable to SSH)
- Security options
- Serve read-only over HTTPS with encrypted transfer
- Can require signed SSL client certificates (stronger client auth)
- Firewall friendliness
- HTTP/HTTPS ports are commonly allowed through corporate firewalls
#### HTTP Cons
- Setup complexity
- HTTPS Git can be trickier to set up than SSH on some servers
- Otherwise, other protocols offer little advantage over Smart HTTP for serving Git content
- Credential handling for authenticated pushes
- Sometimes more complicated than SSH keys
- Mitigations (credential caching tools)
- Keychain access (macOS)
- Credential Manager (Windows)
- “Credential Storage” referenced for secure password caching setup
### SSH Protocol
- Why it’s common for self-hosting
- SSH is often already installed/configured on servers
- If not, it’s generally easy to set up
- Provides authenticated, encrypted transport
- Clone URL forms
- Explicit SSH URL
- `git clone ssh://[user@]server/project.git`
- scp-like shorthand
- `git clone [user@]server:project.git`
- Username handling
- If not specified, Git assumes your current local username
- Pros
- Easy to set up (SSH daemon is common; admins often know it; OS tools exist)
- Secure
- Encrypted + authenticated transfer
- Efficient
- Data compacted before transfer (like HTTPS/Git/Local)
- Cons
- No anonymous access
- Users need SSH access even for read-only cloning
- Not ideal for open source “browse/clone without accounts”
- If you want anonymous read-only + authenticated writes
- Use SSH for push
- Add another protocol for public fetch (e.g., HTTPS or git://)
### Git Protocol (git://)
- What it is
- A Git-provided daemon
- Listens on port **9418**
- Similar transfer behavior to SSH but:
- **No authentication**
- (No encryption/auth overhead)
- Repository export control
- Repo must contain a file named `git-daemon-export-ok`
- Without it, the daemon won’t serve the repository
- Push behavior
- Typically no pushing
- You *can* enable pushes, but it’s insecure:
- Anyone who discovers the URL could push
- Rare in practice
- Pros
- Often the fastest network transfer option
- Useful for
- high-traffic public projects, or
- very large projects
- when no user authentication is required for read access
- Uses SSH-like transfer mechanism without encryption/auth overhead
- Cons
- No authentication (major downside)
- Usually should not be the only access method
- Common pairing
- Developers: SSH or HTTPS (write access)
- Everyone else: `git://` (read-only)
- Harder to set up than others
- Requires its own daemon
- Needs system integration (xinetd, systemd, etc.)
- Firewall constraints
- Requires port **9418**
- Often blocked behind corporate firewalls
## Getting Git on a Server (self-host setup)
- Scope note (environment assumptions)
- Commands shown are simplified for a Linux-based server
- Possible on macOS or Windows servers too
- Production deployments will differ:
- security measures
- OS tooling
- Step 1: create/export a bare repository
- Requirement
- Export an existing repo into a **new bare repository** (no working dir)
- Create a bare clone
- `git clone --bare my_project my_project.git`
- Naming convention
- bare repos typically end with `.git`
- Rough equivalent (not identical)
- `cp -Rf my_project/.git my_project.git`
- Result
- Git data only (no checked-out snapshot)
- Directory dedicated to the repository’s internal data
- Step 2: put the bare repository on a server
- Example environment
- Server: `git.example.com`
- Repos stored under: `/srv/git`
- SSH access available
- Copy bare repo to server
- `scp -r my_project.git user@git.example.com:/srv/git`
- Cloning for other users (with SSH read access to `/srv/git`)
- `git clone user@git.example.com:/srv/git/my_project.git`
- Push access rule of thumb
- SSH + filesystem write permissions to `/srv/git/my_project.git` ⇒ push access
- Group write permissions (recommended)
- Run inside the repo:
- `git init --bare --shared`
- Effects
- Adds group write permissions appropriately
- Does not remove commits/refs/etc.
- Minimal “useful Git server” takeaway
- Add SSH-capable accounts for collaborators
- Place a bare repository where they have read/write permissions
- That’s enough for private collaboration
- What later sections add (optional sophistication)
- avoid per-user accounts
- add public read access
- add web UIs
- etc.
## Small Setups (few developers / trying Git)
- Common pain point
- User management + permissions
- Some repos read-only for some users
- Read/write for others
- SSH Access approach
- If everyone already has SSH access to a server
- Easiest initial setup (almost no additional work)
- For more complex access control
- Use OS filesystem permissions
- If server has no accounts for all writers
- Set up SSH access for those users
- Assumption stated
- If you have a server for this, you likely already have SSH installed and use it to access the server
- Ways to grant SSH write access
- Option 1: create an account for each person
- Straightforward
- Can be cumbersome (adduser/useradd + temporary passwords)
- Option 2: single shared `git` account using `authorized_keys`
- Create one `git` user on server
- Collect users’ SSH public keys
- Append to `~git/.ssh/authorized_keys`
- Everyone connects as `git`
- Commit data unaffected by SSH username used to connect
- Option 3: centralized auth
- LDAP or other central auth source
- Any SSH authentication method works if user can get shell access
### Generating an SSH public key (client side)
- Purpose
- Many Git servers authenticate using SSH public keys
- Each user must generate a key pair if they don’t have one
- Check for an existing key
- SSH keys usually stored in `~/.ssh`
- Example checks
- `cd ~/.ssh`
- `ls`
- Look for pairs like
- `id_dsa` + `id_dsa.pub`
- `id_rsa` + `id_rsa.pub`
- Meaning
- `.pub` file = public key
- non-`.pub` file = private key
- Generate a key if missing
- Tool
- `ssh-keygen` (Linux/macOS SSH package; also included with Git for Windows)
- Recommended command shown
- `ssh-keygen -o`
- Prompts and outputs
- Choose file path (default `~/.ssh/id_rsa`)
- Enter passphrase twice (optional)
- Key is saved as:
- private key: `~/.ssh/id_rsa`
- public key: `~/.ssh/id_rsa.pub`
- Passphrase guidance
- Can be empty (no password prompts when using the key)
- If you do set a password
- use `-o` (more resistant key format than default)
- `ssh-agent` can help avoid typing passphrase repeatedly
- Sharing the public key
- User sends the contents of the `.pub` file to the admin
- Example command
- `cat ~/.ssh/id_rsa.pub`
- Reference link mentioned
- GitHub SSH key guide:
- `https://docs.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent`
### Setting up the server (authorized_keys method)
- Note about automation
- Much can be automated with `ssh-copy-id` (instead of manual key install)
- Create the `git` user and SSH directory
- `sudo adduser git`
- `su git`
- `cd`
- `mkdir .ssh && chmod 700 .ssh`
- `touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys`
- Add developer public keys
- Assumption
- Trusted public keys saved to temporary files (e.g., `/tmp/id_rsa.john.pub`)
- Append to `authorized_keys`
- `cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys`
- `cat /tmp/id_rsa.josie.pub >> ~/.ssh/authorized_keys`
- `cat /tmp/id_rsa.jessica.pub >> ~/.ssh/authorized_keys`
- Create a bare repository on the server
- `cd /srv/git`
- `mkdir project.git`
- `cd project.git`
- `git init --bare`
- First push into the empty bare repository (example workflow)
- Note
- Someone must create a bare repo on the server for each new project
- Example (on John’s computer)
- `cd myproject`
- `git init`
- `git add .`
- `git commit -m 'Initial commit'`
- `git remote add origin git@gitserver:/srv/git/project.git`
- `git push origin master`
- Typical collaboration thereafter
- Clone
- `git clone git@gitserver:/srv/git/project.git`
- Edit/commit/push example
- `cd project`
- `vim README`
- `git commit -am 'Fix for README file'`
- `git push origin master`
- Restricting interactive shell access (optional)
- Default situation
- Users can log in and get a shell as `git`
- Approach
- Change shell in `/etc/passwd`
- Use `git-shell` (limited shell bundled with Git)
- Allows Git push/pull via SSH
- Denies normal interactive shell access
- Ensure `git-shell` is listed as a valid shell
- Check `/etc/shells`
- `cat /etc/shells`
- Find `git-shell`
- `which git-shell`
- Add its path to `/etc/shells` if missing
- `sudo -e /etc/shells`
- Set login shell for user
- `sudo chsh git -s $(which git-shell)`
- Result of interactive SSH attempt
- `ssh git@gitserver`
- Message includes
- `fatal: Interactive git shell is not enabled.`
- hint about `~/git-shell-commands` existing and being executable/readable
- Customize git-shell behavior
- Create `~/git-shell-commands`
- Possible customizations
- restrict accepted Git commands
- customize the SSH login rejection message
- Reference
- `git help shell`
- Preventing SSH forwarding features (optional hardening)
- Even with `git-shell`, users may still use SSH port forwarding
- To prevent, prepend options to each key line in `authorized_keys`
- `no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty`
- Effect
- Git network commands still work
- Users can’t get a shell / can’t use those forwarding mechanisms
## Git Daemon (Git protocol: git://)
- Purpose
- Fast, unauthenticated access to Git data
- Security reminder
- Not authenticated
- Anything served is public within its network
- Recommended use
- Outside firewall: only for publicly visible projects
- Inside firewall: useful for many read-only consumers (e.g., CI/build servers) without managing many SSH keys
- Run the daemon (base command)
- `git daemon --reuseaddr --base-path=/srv/git/ /srv/git/`
- Options
- `--reuseaddr`
- Restart without waiting for old connections to time out
- `--base-path=/srv/git/`
- Allows cloning without specifying full paths
- Trailing `/srv/git/`
- Where to look for repos to export
- Firewall
- Open port `9418`
- Daemonizing & supervising the process
- Depends on OS/init system
- systemd example (common on modern Linux)
- Create `/etc/systemd/system/git-daemon.service`:
- `[Unit]`
- `Description=Start Git Daemon`
- `[Service]`
- `ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/`
- `Restart=always`
- `RestartSec=500ms`
- `StandardOutput=syslog`
- `StandardError=syslog`
- `SyslogIdentifier=git-daemon`
- `User=git`
- `Group=git`
- `[Install]`
- `WantedBy=multi-user.target`
- Adjust as needed
- Ensure the `git` user exists or change user/group
- Verify Git binary path is `/usr/bin/git` (change if needed)
- Service control
- Enable on boot: `systemctl enable git-daemon`
- Start: `systemctl start git-daemon`
- Stop: `systemctl stop git-daemon`
- Other alternatives mentioned
- xinetd
- sysvinit scripts
- anything that daemonizes + monitors the process
- Exporting repositories over git://
- Per-repository opt-in via file:
- `cd /path/to/project.git`
- `touch git-daemon-export-ok`
## Smart HTTP (Git over HTTP with smart negotiation)
- Goal
- One protocol that can provide both:
- authenticated push/pull
- unauthenticated read-only access
- Mechanism
- Enable Git’s CGI script: `git-http-backend`
- How it behaves
- CGI reads URL path + headers from `git fetch` / `git push`
- Determines if client supports Smart HTTP (true for clients since Git 1.6.6)
- If client is smart
- speaks Smart HTTP
- Else
- falls back to Dumb HTTP behavior (backward-compatible reads)
- Basic Apache setup example
- Install Apache + utilities
- `sudo apt-get install apache2 apache2-utils`
- Enable needed modules
- `a2enmod cgi alias env`
- Enables: `mod_cgi`, `mod_alias`, `mod_env`
- Ensure Apache can read/write repositories
- Set group of `/srv/git` to `www-data`:
- `chgrp -R www-data /srv/git`
- Rationale
- Apache CGI runs as `www-data` by default
- Apache configuration for `/git` path
- Environment variables
- `SetEnv GIT_PROJECT_ROOT /srv/git`
- `SetEnv GIT_HTTP_EXPORT_ALL`
- Route `/git/` to the backend
- `ScriptAlias /git/ /usr/lib/git-core/git-http-backend/`
- Note about `GIT_HTTP_EXPORT_ALL`
- If omitted:
- unauthenticated clients can only access repos containing `git-daemon-export-ok`
- Authenticate writes (example Auth block)
- `<Files "git-http-backend">`
- `AuthType Basic`
- `AuthName "Git Access"`
- `AuthUserFile /srv/git/.htpasswd`
- `Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)`
- `Require valid-user`
- Create `.htpasswd` (example user `schacon`)
- `htpasswd -c /srv/git/.htpasswd schacon`
- Notes
- Many authentication methods exist in Apache; this is just a simple example
- Strongly recommended to use SSL so data is encrypted
- Key architectural point
- `git-http-backend` handles Git protocol negotiation and data transfer
- Authentication is handled by the *web server layer* (Apache or other CGI-capable server)
- Web server flexibility
- Works with nearly any CGI-capable web server
- Reference (Apache auth docs)
- `https://httpd.apache.org/docs/current/howto/auth.html`
## GitWeb (simple web UI)
- Motivation
- After enabling read/write and/or read-only access, you may want a basic web visualizer
- What it is
- Git includes a CGI script called **GitWeb**
- (Figure 49 referenced as the GitWeb UI screenshot)
- Quick temporary instance: `git instaweb`
- Uses a lightweight web server (e.g., `lighttpd` or `webrick`)
- Linux note
- `lighttpd` often installed → `git instaweb` may “just work”
- macOS note (example)
- Ruby (and thus `webrick`) may be a convenient choice
- Start with a specified handler
- `git instaweb --httpd=webrick`
- Starts HTTP server on port `1234` and opens a browser automatically
- Example log lines shown include WEBrick and Ruby version info
- Stop the server
- `git instaweb --httpd=webrick --stop`
- Running GitWeb continuously (server deployment)
- Option 1: install a distro package
- Some distros offer a `gitweb` package (via `apt` or `dnf`)
- Option 2: install manually (quick walkthrough)
- Clone Git source (GitWeb included)
- `git clone git://git.kernel.org/pub/scm/git/git.git`
- Build GitWeb with project root configured
- `cd git/`
- `make GITWEB_PROJECTROOT="/srv/git" prefix=/usr gitweb`
- Generates `gitweb.cgi` + static assets (e.g., `static/gitweb.js`)
- Deploy to web directory
- `sudo cp -Rf gitweb /var/www/`
- Apache VirtualHost example (CGI enablement)
- `<VirtualHost *:80>`
- `ServerName gitserver`
- `DocumentRoot /var/www/gitweb`
- `<Directory /var/www/gitweb>`
- `Options +ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch`
- `AllowOverride All`
- `order allow,deny`
- `Allow from all`
- `AddHandler cgi-script cgi`
- `DirectoryIndex gitweb.cgi`
- `</Directory>`
- `</VirtualHost>`
- Result
- Visit `http://gitserver/` to browse repositories
- Server flexibility
- Can be served by any CGI-/Perl-capable web server
## GitLab (modern, fully featured Git server example)
- Why mentioned
- GitWeb is simplistic
- GitLab is a popular open source alternative:
- more capable
- more complex to install/maintain
- database-backed web application
### Installation
- Recommended approach
- Install via official **Omnibus GitLab** package
- Other installation options listed
- GitLab Helm chart (Kubernetes)
- Dockerized GitLab packages (Docker)
- Install from source
- Cloud providers / platforms
- AWS
- Google Cloud Platform
- Azure
- OpenShift
- Digital Ocean
- Reference mentioned
- GitLab Community Edition (CE) README
### Administration (web UI)
- Access method
- Browser to GitLab hostname/IP
- Log in as admin
- Default credentials (must change immediately)
- Username: `admin@local.host`
- Password: `5iveL!fe`
- Entering admin interface
- Click “Admin area” icon (top right menu)
- (Figure 50 referenced)
### Users
- Requirement
- Everyone must have a GitLab user account
- Account contents
- Personal info tied to login data
- Namespaces
- Each user has a namespace grouping their projects
- Example
- user `jane`, project `project`
- URL: `http://server/jane/project`
- Removing accounts (two modes)
- Blocking
- Prevents login
- Preserves namespace data
- Commits signed with that email still link to profile
- Destroying
- Removes user from database and filesystem
- Deletes projects/data in their namespace
- Removes groups they own
- More permanent/destructive; rarely needed
- (Figure 51 referenced as user admin screen)
### Groups
- Definition
- Collection of projects + access control data for those projects
- Group namespace
- Similar to user namespaces
- Example
- group `training`, project `materials`
- URL: `http://server/training/materials`
- Permissions
- Group users have permission levels for group and projects
- Range example
- Guest: issues/chat only
- Owner: full control (group, members, projects)
- Too numerous to list (GitLab links from admin screen)
- (Figure 52 referenced as group admin screen)
### Projects
- Meaning
- Roughly corresponds to a single Git repository
- Namespace association
- Every project belongs to exactly one namespace:
- user, or
- group
- Access control behavior
- User-owned project
- owner directly controls access
- Group-owned project
- group member permissions apply
- Visibility levels (read access control)
- Private
- owner explicitly grants access to specific users
- Internal
- visible to any logged-in user
- Public
- visible to anyone
- Applies to both
- `git fetch` access
- web UI access
### Hooks
- Hook support
- Project-level hooks
- System-level hooks
- Behavior
- GitLab sends HTTP POST with descriptive JSON when events occur
- Purpose
- Integrate with automation and tooling
- CI servers
- chat rooms
- deployment tools
### Basic Usage
- Create a project
- Click “+” icon on toolbar
- Provide
- project name
- namespace
- visibility level
- Most settings can be changed later
- Click “Create Project”
- Connect project to local Git workflow
- Access methods
- HTTPS
- SSH
- URLs shown at top of project home page
- Add remote for an existing local repository (example remote name `gitlab`)
- `git remote add gitlab https://server/namespace/project.git`
- Or clone if you don’t have a local copy
- `git clone https://server/namespace/project.git`
- Web UI repository views
- Project home: recent activity
- Navigation links: files view + commit log
### Working Together
- Model 1: direct push access
- Add users via project settings → “Members”
- Assign access level
- “Developer” or above can push commits/branches directly
- Model 2: merge requests (more decoupled)
- Users with push access
- create branch
- push commits
- open merge request back into `master` (or another branch)
- Users without push permission
- fork project
- push to fork
- open merge request from fork into main project
- Benefits
- owner controls what/when changes merge
- supports contributions from untrusted users
- Discussion units
- Merge requests + issues are main long-lived discussion objects
- Merge requests support
- line-by-line discussion (lightweight code review)
- overall discussion thread
- Both can be
- assigned to users
- organized into milestones
- Broader feature note (beyond Git)
- Also provides features like
- project wikis
- system maintenance tools
- Operational benefit
- after initial setup, little need for config-file edits or SSHing to server
- most admin/usage via browser UI
## Third Party Hosted Options
- When to choose
- You don’t want to set up/maintain your own Git server
- Advantages
- quick setup
- easy project creation
- no maintenance/monitoring
- even if you self-host internally:
- public hosting for open source can be easier for the community to find/contribute
- Choosing a host
- Many options with different pros/cons
- Up-to-date list referenced
- GitHosting page on the main Git wiki:
- `https://git.wiki.kernel.org/index.php/GitHosting`
- GitHub note
- GitHub covered in detail in the “GitHub” chapter
- It’s the largest Git host, and you may need to interact with GitHub-hosted projects
- Many other hosts exist if you prefer alternatives
## Summary (decision guidance)
- You have multiple options for running a remote Git repository to collaborate/share work
- Self-hosting
- Pros
- high control
- can run within your firewall
- Cons
- time/effort to set up
- ongoing maintenance burden
- Hosted services
- Pros
- easy to set up and maintain
- Cons
- your code resides on someone else’s servers
- some organizations prohibit this
- Practical takeaway
- Choose the solution (or combination) that fits your organization’s needs