chepner's answer covers the overall principles. There are a few other subtleties that you want to take note of.
First, login shells do not source .bashrc even if they are interactive. Thus, you probably want a .bash_profile that contains code like the following:
interactive() { [[ $- = *i* ]]; }
interactive && . $HOME/.bashrc || echo 1>&2 "ERROR: .bashrc failed with retval $?"
This won't make much difference on a console login into a graphical environment, but will make quite a difference on a text console or ssh login.
You don't necessarily need to do the interactive test; I actually source .bashrc even for non-interactive shells (though this is arguably not a good idea in some circumstances).
Note that if you use non-Bash shells as well, you'll also need a .profile with whatever environment variables etc. you want for those. Bash will ignore your .profile when you have a .bash_profile, but of course the latter can source the former.
Not every fresh login (i.e., a shell created not by your user id but by a root process that has authenticated you) is considered a "login shell." In particular, giving a command to an ssh invocation (ssh somehost.example.com 'echo $-') will not be a "login shell" and .bash_profile/.bash_login/.profile will not be sourced. Here's a table showing what's considered a "login" or interactive shell and what's executed for various invocations
| State |
Invocation |
| Login (L) |
argv[0][0] == '-', --login |
| Interactive (I) |
-i, stdin is tty |
| Remote (R) |
stdin is "network connection" (see below) |
- '•' = set; blank = not set; '-' = not checked or don't care.
- inh: Inherits environment from a parent (other than init);
i.e., it's not a "fresh login" and the parent may expect that
the environment be kept intact.
- p: sources
/etc/profile
then first of ~/.bash_profile, ~/.bash_login, ~/.profile
- rc: sources
/etc/bash.bashrc then ~/.bashrc
| L |
I |
R |
|
inh |
p |
rc |
|
Example |
| • |
• |
- |
|
|
• |
|
|
ssh host.com (sshd sets argv[0]="-bash") |
| • |
|
- |
|
|
• |
|
|
ssh host.com </dev/null (sshd sets argv[0]="-bash") |
|
• |
|
|
• |
|
• |
|
bash -i, bash on tty |
|
|
|
|
• |
|
|
|
bash hello.sh, bash -c echo foo, |
|
|
• |
|
|
|
• |
|
ssh host.com 'echo $-' (ssh runs bash -c 'echo $-) |
The table comes from this document; there's some further information there that might also be useful. (Anybody who feels something there should be in this answer should feel free to edit this and copy it in.)