Bash Config Setup
A general-purpose baseline for now — the plan is to trim this down to the setup I actually use, and drop the rest.
Bash reads a different startup file depending on how the shell was started — login vs non-login, interactive vs non-interactive. Most day-to-day confusion (aliases or PATH changes that “don’t work” in a new terminal) comes from putting config in the wrong file for the shell type actually being launched.
The config files
| File | Read by |
|---|---|
/etc/profile | Every login shell, system-wide, before any per-user file. |
~/.bash_profile | An interactive login shell — checked first. |
~/.bash_login | Used only if ~/.bash_profile doesn’t exist. |
~/.profile | Used only if neither of the above exists (also read by sh and other POSIX shells). |
~/.bashrc | An interactive non-login shell (e.g. a new terminal tab, or a shell opened from inside another shell). |
/etc/bash.bashrc | System-wide equivalent of ~/.bashrc, read before it. |
~/.bash_logout | Run when an interactive login shell exits. |
$BASH_ENV file | A non-interactive shell (e.g. a script), if that variable is set — otherwise no startup file is read at all. |
Login vs non-login, interactive vs non-interactive
| Shell type | Example | File Bash reads |
|---|---|---|
| Login, interactive | SSH-ing into a machine; a fresh Git Bash window (with -l) | /etc/profile, then the first of ~/.bash_profile / ~/.bash_login / ~/.profile |
| Non-login, interactive | A new terminal tab in an already-logged-in desktop session | /etc/bash.bashrc, then ~/.bashrc |
| Non-login, non-interactive | A shell script, a cron job | $BASH_ENV, if set — nothing otherwise |
Crucially, login shells do not automatically read ~/.bashrc — that’s why aliases defined only in ~/.bashrc can seem to vanish in a login shell (e.g. over SSH) even though they work fine in every new terminal tab.
The standard fix: source .bashrc from .bash_profile
The common convention is to keep all actual configuration in ~/.bashrc, and make ~/.bash_profile just source it — so login shells pick it up too:
# ~/.bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fiWith this in place, it doesn’t matter which file a given shell reads first — the same config always ends up loaded.
Git Bash specifics
Git for Windows’ Bash behaves like a standard login shell by default, which is why ~/.bash_profile (not ~/.bashrc) is the file that actually runs when you open a fresh Git Bash window — unless it sources ~/.bashrc as above.
- Git Bash’s
$HOMEisC:\Users\<you>— the same files apply as on Linux/macOS, just under that path. - If neither
~/.bash_profilenor~/.profileexists, Git Bash falls back to its own built-in/etc/profile, which already sources/etc/bash.bashrcand sets up a reasonablePATH— creating~/.bash_profileis what lets you extend that instead of replacing it. - Terminal appearance (fonts, colors, keyboard shortcuts) is a separate layer handled by mintty, not Bash — see Git Bash for Windows Setup.
What typically goes in .bashrc
| Category | Example |
|---|---|
| Aliases | alias ll='ls -la' |
PATH additions | export PATH="$HOME/.local/bin:$PATH" |
| Environment variables | export EDITOR=vim |
| Prompt customization | export PS1='\u@\h:\w\$ ' |
| Functions | mkcd() { mkdir -p "$1" && cd "$1"; } |
| Sourcing extra files | [ -f ~/.git-completion.bash ] && . ~/.git-completion.bash |
Applying changes
Edits to .bashrc or .bash_profile don’t take effect in windows that are already open.
| Command | Description |
|---|---|
source ~/.bashrc | Re-run the file in the current shell. |
. ~/.bashrc | Equivalent shorthand — . is the POSIX form of source. |
| Open a new terminal window | Simplest option; picks up whichever file applies to that shell type. |