bashrc vs bash_profile - What are the differences?
So, if you are familiar with any Unix-like system you might get found one of those files at least once in your life - mostly to tweak the PATH variable, or perhaps to add some exports as well.

If not, fear not! Today we'll check them very closely and see what are their purpose, what makes them different and how to use them correctly!

So let's start...


Start up scripts

At initialization the bash(1) will execute a myriad of files. Differently from the normal bash scripts, those files don't need to have the executable bit set and don't need to have the shebang as well.

The order of execution is well defined and is like the follow:

For interactive login shell:
   1 - /etc/profile
   2 - ~/.bash_profile, ~/.bash_login, ~/.profile
The step #1 can fail if the files doesn't exists (but isn't an error).
The step #2 will only execute the first file that was found.

For interactive non-login shell:
   1 - /etc/bash.bashrc
   2 - ~/.bashrc
Both steps can fail if the file isn't found, but none of them are errors.


Differences

So we just saw that bash_profile is executed when we have an interactive LOGIN shell and bashrc is executed when we have an interactive NON-LOGIN shell.

But what that means in reality?

Interactive LOGIN shell: As the name states is the "type" of shell that is spawned when we (might) need to enter our credentials at usage. As examples we might say when you first login into your machine, or perhaps when you login via ssh(1) into a it.
Here everything that inside bash_profile will be executed, but not the other start up scripts.

Interactive NON-LOGIN shell: Is the "type" of shell that is created when we don't need use our credentials to use it. The first example that comes to mind is when you open a new xterm(1) instance or runs /usr/bin/bash.
As you might expect, on those situations the bashrc file will be executed, but not any of the other files.


Oh my dear macOS!

If you try to create a bashrc file on macOS and test the initialization order that we learned before we'll see that this isn't working correctly at all. Every time the Terminal.app seems to execute only the bash_profile.

What is going on is that, for some reason, Apple decided that the Terminal.app will by default spawn interactive login shell every single time.
So like we already know, only the bash_profile will be executed.


References

1- wikipedia
2- joshstaiger
3- bash manpage
4- scriptingosx
Creative Commons Licence