I'm trying to understand the git version control, but I'm unable to find good information about it / how you use it.
Currently I push to my test repo and test it, if it works I merge it into prod and pull it on to the server. If something goes wrong I don't think I have a good way to rollback.
Some information on this would be awesome, links / blog posts with examples highly appreciated.
Version control in general works like this:
You have a mainline branch of code called the trunk. This is the code that will be used in released software.
When you want to make changes in software, you branch off the trunk. You then do development in this branch of code. The reason you do this is if someone else wants to make changes, they can branch off the trunk. This is to ensure that none of their changes are affecting you and vice versa. If you both were to work from the trunk directly, you could potentially pollute each other's work with bugs and other strange behavior. It also pollutes the trunk with software that isn't ready for release (remember, the trunk is supposed to represent tested, stable-as-possible software)
When you're done with making changes to your branch and you've sufficiently tested it, you merge it back to the trunk. Similarly, if someone else made a branch and is done with it, they also merge it back into the trunk.
Once all the branches are merged in, you should do a test on the trunk that does the same tests that were done on the branches to ensure they all play nicely with each other.
Any changes regarding what the branch is supposed to do should be re-branched from the trunk. This is more of a convenience factor because version control software can flag some changes as conflicts and if you're trying to merge in a branch from an old trunk into a future trunk, it's going to complain loudly. It also makes it harder for you to successfully merge in code, especially if the source file that was touched was touched by a few other branches.
Once all branches are merged and the trunk tested, you create a tag of the trunk. This is more of a checkpoint so you don't have to find which revision number this finalization occurred.
As an example, I have Super Amazing Software version 1.00 I'm working on.
I have the trunk for version 1.00, and I want to do work for a version 1.01 release by adding a few features
I first create 1.01's trunk based on 1.00's trunk.
I make a branch for each feature I want to add. Each branch will only have that feature implemented.
After I test each branch to ensure the new feature works, I merge the branch back into 1.01's trunk.
After all the branches are merged in, I do some testing to make sure the software works when everything's together.
I find out something is broke and isolate to a particular branch.
I rebranch the trunk to make the fix. Then it gets merged in and it all gets retested.
Everything passes, so I make a tag for this version. If no other features are planned for this version, it gets released.
If there are more features planned, the process restarts from the third step.