This guide aims to provide a basic introduction of Git but also brings some insights to how Git actually works under the hood. After reading this guide, you should learn how to properly version control your projects, understand how branching works, and synchronize your changes to remote services such as GitHub or GitLab.
Large software projects aren't built in a single day by a single person. Most people start out learning to code without properly managing different changes made to their code base.
Those methods can works when you are just learning or your project relatively small. However, as the scale grows or more people joins your project, things can easily go out of hand:
Git is an open source and distributed version control system. It is the most popular tool for companies and open source software to manage their projects. Git not only allows large teams to collaborate seamlessly and work in parallel, but it's also perfect for experimenting or developing new features on your own without breaking your working code. It also features an immutable version history, that is, developers can't simply make a change to an older version without others noticing (similar to a blockchain).
Because Git is such as powerful and flexible tool, developers must be fully aware what they are doing when entering a command. Wrong commands can range from losing your work to potentially breaking other coworkers' developing environment.
A commit is the smallest unit of Git, it is represented by a SHA1 unique hash called the commit ID. It captures the current state of the code base and the previous commit. Any changes to the state of the code base (modifying text, time of commit, previous commits, and more) will alter the commit ID, thus creating the chain of trust. This ensures data integrity, if two commit IDs are the same, the code is guaranteed to be exactly the same.
When you made a lot of changes to code base and it's time to commit, you probably don't to commit everything at once because you want to group related changes. This is where staging comes into play. You need to add changes to the stage area of Git before you can commit time changes.
For example, we created a frontend/login.html
file and made changes to two other files called backend/login.py
and backend/get_products.py
We can use
to add those changes to staging
Then we commit those changes with a meaningful commit message:
And we repeat those same steps again
Git tracks both additions and deletions of files so make sure to add deletions to staging as well. For instance, if you removed ``
It is considered good practice review your changes before committing to avoid tracking unwanted files, it also provides you a time to tidy up your changes or double check for errors.
You can do this withgit status
andgit diff
in the terminal, but modern IDEs and editors often come with great Git integration that lets you view changes in a graphical way.
Branches are one of the killer features of Git. A branch can be thought of as a pointer pointing to a commit. When you commit a change on a branch, Git automatically moves the pointer forward to the latest commit. When merging two branches, Git looks for differences between the two from where they derive. This means two branches without a common history cannot be merged*.
For example, we want to develop a new feature on our project
First we create a new branch using
where feature-1
can be any suitable name you want.
When we finished developing the feature and we want to merge it back to the main
branch
*Yes --allow-unrelated-histories
exists but that is beyond the scope of this article
An important thing to note is because Git is a fully distributed system, there isn't a "local" and "remote" concept from a pure Git standpoint. But due to the nature of software development, we often keep one server(or services such as GitHub and GitLab) as the single source of truth and developers clone the repo from the "remote" server.
To clone from a remote repo
To sync changes from the remote server use
To sync changes to the remote server use
Viewing Git history in a GUI can be really helpful when your project grows