Andrew Mercer
on this page

02 · Repositories and Remotes

← Overview · Prev: Setup · Next: Everyday workflow →

Create or clone

git init                                  # new repo in the current directory
git init --bare /srv/git/project.git      # server-side repo (no working tree)

git clone <remote-url>
git clone <remote-url> <dir>              # choose the directory name
git clone -b <branch> <remote-url>        # check out a specific branch
git clone --depth 1 <remote-url>          # shallow clone: latest snapshot only
git clone --filter=blob:none <remote-url> # partial clone: fetch file contents on demand
git -c http.sslVerify=false clone <remote-url>   # skip TLS verification (self-signed lab servers ONLY)

git-adm: git-adm clone <url|name> [--branch B] [--dest D] [--ssh-key K] [--insecure]. A bare repo name expands using clone_base_url from ~/.git-adm.conf.

Bare repositories (server side)

A bare repo has no working tree. It contains what is normally in .git/: HEAD config description hooks info objects refs.

git init --bare /srv/git/project.git
git clone ssh://user@host/srv/git/project.git

Rules of thumb: developers push to bare repos; nobody edits files inside them. Pushing to the checked-out branch of a non-bare repo is refused for good reason.

git-adm: git-adm init-bare <path>...

Remotes

A remote is just a named URL plus a set of tracking refs (origin/main, origin/feature, ...).

git remote -v                          # list remotes and URLs
git remote add upstream <url>          # add a second remote (typical for forks)
git remote set-url origin <new-url>    # change a URL
git remote rename origin gitlab
git remote remove <name>
git remote show origin                 # branches, tracking and ahead/behind info
git remote prune origin                # delete stale tracking refs (or use fetch.prune)

git-adm: git-adm remote show, git-adm remote set-url <url>

Forks: origin + upstream

git remote add upstream <original-repo-url>
git fetch upstream
git switch main
git rebase upstream/main        # or merge; keep your fork's main in sync
git push origin main

Fetch, pull, push

Command What it does
git fetch Download new objects and update origin/* refs. Never touches your branches or working tree.
git pull fetch + integrate (merge, or rebase if pull.rebase=true).
git push Upload your commits and move the remote branch. Refused if it would lose remote commits.
git push --force-with-lease Force-push only if the remote is still where you last saw it.
git push -u origin HEAD Push the current branch and set its upstream.

Tracking and ahead/behind:

git branch -vv                          # each branch, its upstream, ahead/behind
git rev-list --left-right --count HEAD...@{u}    # "ahead  behind"
git status --short --branch

Clone but exclude one file (sparse checkout)

Handy when a tool wants to overwrite one file in a shared checkout.

git init <dir> && cd <dir>
git remote add -f origin <remote-url>
git config core.sparseCheckout true
printf '/*\n!<file-to-exclude>\n' > .git/info/sparse-checkout
git pull origin main

Modern alternative: git sparse-checkout set <dir1> <dir2> to check out only some directories.

Submodules (brief)

A submodule pins another repository at a specific commit inside yours.

git clone --recurse-submodules <url>
git submodule update --init --recursive     # after a plain clone or a pull
git submodule update --remote               # move submodules to their latest upstream commit

Remember to commit the updated submodule pointer in the parent repo.