# How to Use Git ## How to Use This Guide 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. ## Why Should You Use a Version Control System 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. ![](https://hackmd.io/_uploads/HJiuada0n.png) 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: * What if an old bug was discovered and you need to apply changes to multiple versions? * How can you know every change your teammate made (or even by yourself last week)? * What happens when you and your teammate make different changes to the same file? * Do you also copy your build files or dependencies? * Lots of duplicated files without any change can take up a lot of space ## What is Git 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. ## Commit 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 ```bash git add frontend/login.html backend/login.py ``` to add those changes to staging Then we commit those changes with a meaningful commit message: ``` git commit -m "added login page" ``` And we repeat those same steps again ``` git add backend/get_product.py git commit -m "fixed bug where" ``` ```mermaid %%{ init: { 'theme': 'base' } }%% gitGraph: commit id: "e83c516331" commit id: "8bc9a0c769" commit id: "e497ea2a9b" commit id: "bf0c6e839c" commit id: "19b2860cba" tag: "HEAD" ``` ```mermaid %%{ init: { 'theme': 'base' } }%% gitGraph: commit id: "e83c516331" commit id: "8bc9a0c769" commit id: "e497ea2a9b" commit id: "bf0c6e839c" commit id: "19b2860cba" commit id: "24778e335a" tag: "HEAD" ``` > 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 with `git status` and `git diff` in the terminal, but modern IDEs and editors often come with great Git integration that lets you view changes in a graphical way. ## Branch 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 ``` git switch -C feature-1 ``` 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 ``` git switch main git merge feature-1 ``` ```mermaid %%{ init: { 'theme': 'base' } }%% gitGraph: commit id: "e83c516331" commit id: "8bc9a0c769" branch feature-1 commit id: "e497ea2a9b" commit id: "bf0c6e839c" commit id: "19b2860cba" checkout main merge feature-1 commit id: "24778e335a" tag: "HEAD" ``` \*Yes `--allow-unrelated-histories` exists but that is beyond the scope of this article ## Local and Remote 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 ``` git clone <remote-url> ``` To sync changes from the remote server use ``` git pull ``` To sync changes to the remote server use ``` git push ``` ## Useful Tools Viewing Git history in a GUI can be really helpful when your project grows ## Resources * [Visual Git Cheat Sheet](https://ndpsoftware.com/git-cheatsheet.html)