The "undefined reference" is a linker error. Compilation has multiple steps.
First, compiler creates an object file from translation unit.
https://en.wikipedia.org/wiki/Translation_unit_%28programming%29
The unit is basically the .cpp file, but with all includes inserted (preprocessor assembles the unit according to directives for the compiler).
An object file must be created for each necessary translation unit. Your main.cpp and Stack.cpp are two separate units.
Libraries are essentially archives of object files that somebody else has already compiled and packaged.
The linker creates executable binary file by combining the object files that you give to it. If one object refers to code that it does not have (e.g main.o has a call for Stack::Push) then an object file or library containing the code of Stack::Push must also be in linker's command line arguments.
You, however, have a twist: Stack
<int>::Push
Template.
When your main has a call to Push() of Stack<int>, the compiler first attempts to create source code for Stack<int>::Push from the templates
available in the main.cpp's translation unit. It must see the templates. Object code is created according to the generated source.
Nothing in the Stack.cpp's translation unit is likely to instantiate the Stack<int> and thus the corresponding object file will lack that implementation. (There are ways to force stuff, particularly for libraries, but that is tricky.)
C++ has one definition rule (ODR). When you link, only one object file may contain code for any one entity. (Otherwise you get "multiple definitions" linker error.) The template-based code gets around ODR; the linker knows to discard all but one copy.
C++ standard had "extern template implementation" syntax, but since no compiler developer managed to make a decent implementation, it was removed.
Summary: template code cannot be in separate .cpp. It has to be included.
How to organize code into files then? That is a matter of style.
(Or not. MS Visual C++ used to accept member function implementations only within the template class definition.)
For example: put definition of class into Stack.hpp and include the file containing the class member implementations into the Stack.hpp after the definition. Then a user (main.cpp) sees all of Stack by including Stack.hpp
Naming the files and filename extensions.
There are no hard rules, but a (human) reader can guess more easily if you are systematic.
Build systems (including IDE's) can automate if you do use extensions that they are made to expect.