Files
mapas-mentales/mindmap/Git on the Server.md

28 KiB
Raw Blame History

# 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:
    - Its 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 dont want to self-host)
  - If you dont 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 projects `.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 someones 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 doesnt 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 its common for self-hosting
  - SSH is often already installed/configured on servers
  - If not, its 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 wont serve the repository
- Push behavior
  - Typically no pushing
  - You *can* enable pushes, but its 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 repositorys 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
  - Thats 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 dont 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 Johns 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 cant get a shell / cant 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 Gits 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 dont 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 dont 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
  - Its 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 elses servers
    - some organizations prohibit this
- Practical takeaway
  - Choose the solution (or combination) that fits your organizations needs