Installing Git and configuring your environment

Install on any platform, set the identity and configuration that actually matter, control line endings, and put shared rules in the repository instead of in your head.

Install and verify

# macOS
brew install git

# Debian / Ubuntu
sudo apt update && sudo apt install git

# Fedora
sudo dnf install git

# Windows
winget install --id Git.Git -e

# whichever platform you are on, confirm what you got
git --version
git config --list --show-origin
PlatformRecommended installNote
macOSbrew install gitDo not rely on the version bundled with the Xcode command line tools, which lags behind
Debian / Ubuntuapt install gitDistro packages can be old; a newer release adds hooks and options you will want
Fedora / RHELdnf install gitThe git-core package is usually enough on servers
Windowswinget install Git.GitAlso installs Git Bash, which gives you a usable POSIX shell
Anygit help configThe full reference ships offline with the binary

Installing Git also installs its documentation: git help <command> works without a network connection and describes the version you actually have, which a search result rarely does.

The configuration that matters

git config --global user.name "Ada Lovelace"
git config --global user.email "[email protected]"

git config --global init.defaultBranch main
git config --global core.editor "code --wait"     # --wait keeps Git from returning early
git config --global pull.rebase true
git config --global rerere.enabled true
git config --global fetch.prune true
git config --global rebase.autosquash true
git config --global alias.st "status -sb"
git config --global alias.lg "log --oneline --graph --decorate --all"

# a repository can override any of it, which is how work email happens
git config user.email "[email protected]"
git config --local core.hooksPath .githooks
SettingWhy it matters
user.name / user.emailEvery commit is stamped with them; a wrong address means your work is not attributed to you
init.defaultBranchNew repositories start on main rather than the legacy default
core.editorCommit messages, rebase plans and --amend all open an editor; without --wait Git commits an empty message
pull.rebaseDecides once whether every pull adds a merge commit, instead of asking per command
rerere.enabledReuses a recorded conflict resolution when the same conflict reappears, which happens constantly during a long rebase
fetch.pruneRemoves local references to remote branches that were already deleted
core.hooksPathLets a repository ship hooks in a tracked directory instead of .git/hooks, which is never cloned
💡
Configuration has three levels — system, global and local — and the nearest one wins. git config --list --show-origin prints the file each value came from, which is how you debug the classic "it works on my machine".

Line endings, ignore files and attributes

# .gitignore — patterns apply to untracked files only
node_modules/
dist/
*.log
.env
.env.*
!.env.example
.DS_Store

# .gitattributes — per-path rules that travel with the repository
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
*.png binary

# personal exclusions that should stay out of the repository
git config --global core.excludesFile ~/.gitignore_global
  • Prefer a small, deliberate ignore file over a large copied one: every line nobody can explain is a future mystery.
  • A negation such as !.env.example only works when no parent directory is ignored, so ignoring .env* then excepting a file does not behave as people expect.
  • core.autocrlf=true on Windows converts LF to CRLF on checkout and back on commit; .gitattributes with text=auto achieves the same thing and is shared by the whole team.
  • Ignoring a path does not remove a file that is already tracked — use git rm --cached for that, and remember the content stays in history.

FAQ

I already committed with the wrong email. Can I fix it?
On a local branch that has not been pushed, yes: an interactive rebase with --reset-author, or a history filter over the whole range. If it is already published, do not rewrite it — add a .mailmap entry so the attribution displays correctly.
Should hooks and ignore rules be committed?
Ignore rules and .gitattributes always, because the whole team needs them. Hooks are better kept in a tracked directory and enabled with core.hooksPath than left in .git/hooks, which is not versioned and not cloned.

Hooks, aliases and automation Reading history: log, diff, blame and bisect

Last refreshed 2026-09-18.