Question: What's the difference between `.bashrc` and `.bash_profile` and which one should I use?

Answer: 
From this [short article](http://joshstaiger.org/archives/2005/07/bash_profile_vs.html)

> 
> According to the bash man page,
>  .bash\_profile is executed for login
>  shells, while .bashrc is executed for
>  interactive non-login shells.
> 
> 
> **What is a login or non-login shell?**
> 
> 
> When you login (eg: type username and
>  password) via console, either
>  physically sitting at the machine when
>  booting, or remotely via ssh:
>  .bash\_profile is executed to configure
>  things before the initial command
>  prompt.
> 
> 
> But, if you've already logged into
>  your machine and open a new terminal
>  window (xterm) inside Gnome or KDE,
>  then .bashrc is executed before the
>  window command prompt. .bashrc is also
>  run when you start a new bash instance
>  by typing /bin/bash in a terminal.
> 
> 
>
The configuration logic of bash's itself is not crazy complicated and explained in other answers in this page, on serverfault and in many blogs. The problem however is *what the Linux distributions make of bash*, I mean the complex and various ways they configure bash by default. <http://mywiki.wooledge.org/DotFiles> mentions some of these quirks briefly. Here's one sample trace on Fedora 29, it shows which files source which other file(s) and in which order for a very simple scenario: remotely connecting with ssh and then starting another subshell:

```
ssh fedora29
 └─ -bash # login shell
      ├── /etc/profile
      |    ├─ /etc/profile.d/*.sh
      |    ├─ /etc/profile.d/sh.local
      |    └─ /etc/bashrc
      ├── ~/.bash_profile
      |    └─ ~/.bashrc
      |          └─ /etc/bashrc
      |
      |
      └─ $ bash  # non-login shell
            └─ ~/.bashrc
                 └─ /etc/bashrc
                       └─ /etc/profile.d/*.sh

```

Fedora's most complex logic is in `/etc/bashrc`. As seen above `/etc/bashrc` is a file bash itself doesn't know about, I mean not directly. Fedora's `/etc/bashrc` tests whether:

* it's being sourced by a login shell,
* it's being sourced by an interactive shell,
* it has already been sourced

... and then does completely different things depending on those.

If you think can remember the graph above then too bad because it's not nearly enough: this graph merely describes just one scenario, slightly different things happen when running non-interactive scripts or starting a graphical session. I've omitted `~/.profile`. I've omitted `bash_completion` scripts. For backward compatibility reasons, invoking bash as `/bin/sh` instead of `/bin/bash` changes its behaviour. What about zsh and other shells? And of course different Linux distributions do things differently, for instance *Debian and Ubuntu come with a non-standard version of bas*h, it has Debian-specific customization(s). It notably looks for an unusual file: `/etc/bash.bashrc`. Even if you stick to a single Linux distribution it probably evolves over time. Wait: we haven't even touched macOS, FreeBSD,... Finally, let's have a thought for users stuck with the even more creative ways their admins have configured the system they have to use.

As the never-ending stream of discussions on this topic demonstrates, it's a lost cause. As long as you just want to add new values, some "trial and error" tends to be enough. The real fun begins when you want to *modify* in one (user) file something already defined in another (in /etc). Then be prepared to spend some time engineering a solution that will never be portable.

For a last bit of fun here's the "source graph" for the same, simple scenario on Clear Linux as of June 2019:

```
ssh clearlinux
 └─ -bash # login shell
      ├── /usr/share/defaults/etc/profile
      |    ├─ /usr/share/defaults/etc/profile.d/*
      |    ├─ /etc/profile.d/*
      |    └─ /etc/profile
      ├── ~/.bash_profile
      |
      |
      └─  $ bash   # non-login shell
           ├─ /usr/share/defaults/etc/bash.bashrc
           |      ├─ /usr/share/defaults/etc/profile
           |      |    ├─ /usr/share/defaults/etc/profile.d/*
           |      |    ├─ /etc/profile.d/*
           |      |    └─ /etc/profile
           |      └─ /etc/profile
           └─ ~/.bashrc

```