Andrew Mercer
on this page

01 · Setup and Configuration

← Overview · Next: Repositories and remotes →

Config levels

Git reads config from three places; later ones override earlier ones.

Level File Flag
System /etc/gitconfig --system
Global (per user) ~/.gitconfig or ~/.config/git/config --global
Local (per repo) .git/config --local (default)
git config --list --show-origin      # every setting, and which file it came from
git config --get user.email          # one value, as git resolves it here
git config --global --unset <key>    # remove a setting
git config --global user.name  "Your Name"
git config --global user.email "[email protected]"
git config --global core.editor vim
git config --global init.defaultBranch main
git config --global pull.rebase true          # avoids "divergent branches" errors
git config --global rebase.autoStash true     # stash a dirty tree around a rebase
git config --global fetch.prune true          # drop stale remote-tracking branches
git config --global push.autoSetupRemote true # first push sets upstream automatically
git config --global push.default simple
git config --global core.autocrlf input       # normalise line endings (important on WSL)

What each one buys you:

  • pull.rebase true — git pull becomes fetch + rebase, so you don't accumulate meaningless "Merge branch 'main' of ..." commits and never hit the divergent-branches error.
  • rebase.autoStash — git rebase (and git pull --rebase) works even with uncommitted changes.
  • fetch.prune — deleted remote branches disappear from git branch -r automatically.
  • push.autoSetupRemote — no more --set-upstream on the first push of a branch.
  • core.autocrlf input — CRLF is converted to LF on commit, but files are never rewritten to CRLF on checkout.

git-adm: git-adm setup applies all of these and warns when user.name/user.email are missing.

Useful aliases

git config --global alias.st  "status --short --branch"
git config --global alias.lg  "log --oneline --graph --decorate -20"
git config --global alias.ls  "log --name-status"
git config --global alias.unstage "restore --staged"

Credentials: never put tokens in URLs or ~/.gitconfig

A remote such as https://user:token@host/repo.git, or an insteadOf rewrite containing a token, stores the secret in plain text. It then leaks into git remote -v, shell history, backups and screenshots. Use SSH keys or a credential helper instead.

git config --global credential.helper 'cache --timeout=3600'   # in memory only
# or a helper backed by your OS keyring / password manager

Use a specific SSH key for a single command:

GIT_SSH_COMMAND='ssh -i ~/.ssh/<key> -o IdentitiesOnly=yes' git clone <remote-url>

Or permanently, per host, in ~/.ssh/config:

Host git.example.com
    IdentityFile ~/.ssh/<key>
    IdentitiesOnly yes

git-adm: git-adm clone <url> --ssh-key <key>

Ignoring files

  • .gitignore in the repo — shared with everyone.
  • .git/info/exclude — personal, per repo, not committed.
  • core.excludesFile (e.g. ~/.config/git/ignore) — personal, all repos (editor junk, OS files).
git check-ignore -v <path>          # why is this file ignored?
git ls-files --others --ignored --exclude-standard   # what is currently ignored
git rm --cached <file>              # stop tracking a file that is now in .gitignore

.gitignore only affects untracked files. A file that is already tracked stays tracked until you git rm --cached it.

Show the current branch in your bash prompt

# Locate git-prompt.sh (path varies by distro), or take it from git's contrib/completion/
cp /usr/share/git-core/contrib/completion/git-prompt.sh ~/.git-prompt.sh
# ~/.bashrc
. ~/.git-prompt.sh
export GIT_PS1_SHOWDIRTYSTATE=1
export PS1='[\u@\h \W]$(__git_ps1 " (%s)")\$ '

Tab-completion is provided by git-completion.bash from the same directory.

Shared hooks directory

See Hooks.