Understanding the Basics of Git Version Control
Objective: Get a practical understanding of Git and its main commands
Learning Git on the job provided me with a strong practical knowledge of what to do and when to do it while working as a software engineer.
I will not try to explain what Git is (apart from saying that it’s a version control system), instead I’m going to give some simple information which will make easier to understand its main features.
So, let’s say you and some other developer are working on the same project and want to share each of your contribution to the code; or let’s say that some of your colleagues are going to develop a new feature and chances are they’re going to mess around a little; or let’s say that they already messed up…
Is there a way to keep everything under control? Yep! With version control.
Git (like other version control systems) allows to keep track of every change, plus a bunch of other cool features. But let’s proceed with order.
You have your code on your local machine, you have a remote repository (on GitHub, BitBucket etc.) and through git commands you can “update”, the remote repository by pushing new local changes from local to remote or do the opposite, by pulling the changes from remote to local.
In order to use these commands, git push and git pull, there is workflow to follow. One thing I found very useful is to visualize Git through its areas.
The code you are writing lives in the working directory, in which you have initiate the repository, with the git init command.
After any change, the git status command will show which files have been modified and which are new and untracked. By calling the command git add, followed by a file name or “.” (all the files) you will “move” (or add) the chosen files to the staging area.
At this point you can continue your work, add other files, remove files from the staging area (git restore “fileName”) or commit your changes. By calling git commit -m “message”, you will confirm your changes and move them to the local repository. It is mandatory to label each commit with a more or less short message, explaining the changes themselves.
While the staging area is just temporary, the local repository is stored in the .git folder you can find in your working directory
A this point, git push origin “branchName” command, will send the changes to the remote repo, if local and remote repo are aligned.
A shorter command, git push, can be used if the current branch is set up to track a remote one. But I’ll talk about branches later on.
Always ensure that local and remote repository are aligned, by calling git pull before making any changes
Let’s now continue with a few other useful commands.
There are times in which a parallel development is needed, maybe a new feature or a complex change in an existent feature, and you need to do it safely. In this case the branching feature is very helpful. If no branches were already created, you are probably working on a default branch named “master”. By calling the command git checkout -b “branchName” you will create a new branch, with a name of your choice, starting from master (meaning that the new one is a copy of master branch). Now you can make all the changes you want and they will be committed only on the new branch, leaving master (and others) untouched.
master branch usually contains the final version of your code, while you use other branches for development
git checkout command is also used to switch from a branch to another by simply omitting the option -b: git commit “branchName”. When used in this way, you will be notified if there are non-committed changes
You can also get a list of all branches with the command git branch.
git log command shows the history of commits made in the current branch, from the last to the first one. Each commit has a unique hash code (hexadecimal) identifying it and the last commit is always labelled as HEAD.
If the list is very long, there will be pagination: press Enter to scroll the list and q to exit.
OK, now the dangerous stuff: git reset “commit hash”. This command basically lets you go back in time to a specific commit. Using the soft option, you will go back to the specific commit but will find any successive change available and ready to be staged and commit. hard option, on the other hand will make you lose all those changes… so be careful!
Since HEAD points to the last commit, it is possible to use it as a reference:
git reset HEAD^ — resets to the commit before HEAD
git reset HEAD^n — resets to the nth commit before HEAD
Now that your tree has as many branches as you need, is time to learn how to merge. Let’s say that you created a new branch named newFeature starting from master. Now that the new feature is fully developed, tested and ready, you need to merge it in on the code on master branch. That’s a job for git merge command. By calling git merge “branchName” you are asking to (try and) merge the code on that branch in the code on the current branch. So, in this example you first would checkout master and then merge newFeature.
If you created a new branch for a parallel development and you want to merge back in the end, always merge the old in the new and then the new in old again, in order to keep the new branch always aligned with any changes.
Last, but not least, our friend git fetch. Good-guy fetch can be called, indicating the branch to fetch or a powerful all option, and it simply downloads any change from remote repo, without affecting your local files (as git pull does). It is a useful, non-destructive command that lets you check the existence of any changes (for example made by others) on remote repository. You can consider git fetch as safe version of git pull.
Before learning advanced commands, such as revert or cherry pick, I managed to work just by using the commands explained above. That’s why I chose to put them in this guide: they are very basic commands anyone should know in order to work with git. Always check the documentation if you want to learn more!
Hope this was helpful!! You can find a real life example in articles to come.