DEV Community

Horace FAYOMI
Horace FAYOMI

Posted on

The true power of Git 🔥😤.

Image description

Git is a powerful, no, a super-powerful (💪) tool that plays a fundamental role in modern software development. In this article, we will introduce GIT to those discovering it for the first time and revisit GIT for those who already use it daily, highlighting how incredible it is. We will cover the most commonly used Git commands, including less frequently used ones like git cherry-pick, which are remarkably formidable and powerful. So, dear Geeks 🤓, here is the true power (😤) of GIT explained 😌.

At its core, Git is a distributed version control system. It's an efficient and meticulously organized way to manage your codebase. It allows you to:

  • Track changes made to your project.
  • Have multiple people working together on the same codebase in a clear and organized manner. It's like multiple people simultaneously editing the same Google Docs file online, but with a much higher level of organization and precision, almost surgical.
  • It also keeps a clear history of each person's work. That also means you can know who to blame when there's an issue 🤭.
  • And it provides a valuable safety net, allowing you to revert to a previous version of the code in case of errors, or by allowing you to surgically remove unwanted changes without affecting the project.

To use Git, you need to install it on your computer, whether on Linux, Windows, or macOS. Don't worry; you'll be well-served.

Next, you need to create a Git repository, often called a repo. Repositories are essentially project folders. You can have a local repository on your computer and a remote repository hosted on a platform like GitHub, GitLab, or Bitbucket.

You can create a repository in two ways:

  • The first way is through the command line. First, you create the folder on your machine, then execute the command: git init. After that, you can send a copy of your repository to the remote repo by running git push.
  • The second way is to do the opposite, which is to create the repository directly on the web interface of the remote repository platform. Then, you create a local copy of the repository on your machine by executing the command: git clone. This is called cloning the repo.

Once the repository is created, other people who want to work on the project can clone it to also have a copy of the repo on their own machines.

Let's suppose there are two coders who want to work on the project, and there are two features to implement. Each of the coders will work on a separate feature.

Git allows each coder to work separately and independently on their feature by using what we call a branch. A branch is, in a way, a copy of the project at a specific version. We can create, merge, and delete branches as needed.

By default, every Git repository has a branch, often called main or master, which should contain the project with the unified or final codebase.

To navigate between different branches in the repository, we use the command git checkout branch-name. To create a branch, we execute the git checkout -b branch-name command. Finally, the git branch command lists all the branches in the repository.

Now, let's return to our project. Suppose that essential base files necessary for the coders to work on their features have been added during the project's creation.

The first coder can create a branch called feature-1, in which he will only add the code to implement the first feature. The second coder can create another branch called feature-2 to concurrently handle the second feature.

But most of the time, implementing a feature into a branch is a long process, and is then done iteratively by leveraging one of the tools that make Git so powerful: they are commits 😌.

Commits are the building blocks of the project's history. They represent specific points in time in the evolution of the project within a given branch, akin to progressive versions of the project's codebase.

To implement feature 1, the first coder may decide to break it down into 5 smaller sub-features, each dependent on the others. When he finishes the first sub-feature, he can isolate it into an initial commit, named for example commit-1-of-feature-1. Then, when he finishes the second sub-feature, he adds it to a commit named commit-2-of-feature-1. This process continues until the entire feature is implemented.

Creating a commit also involves three steps. Let's draw an analogy to the manufacturing, packaging, and shipping of products in containers. A single container can hold multiple shipment of products, and a single shipment can contain several products.

In that analogy, a container represents a commit, and the code represents the products to manufacture .

Then.

  • The first step in creating a commit is writing the code, essentially manufacturing the products. By default, this code is stored in what's called the Working directory . It's the folder on the computer where the code resides, much like the industrial production area.
  • The second step is adding the changes to what's known in Git jargon as the staging area or transit zone. In our analogy, this is similar to packaging products and placing them in the warehouse for delivery. This is done using the git add command.
  • The third and final step is creating the commit, and this is when the code is actually added to the local Git repository on our machine. In our analogy, this is equivalent to loading products into the container. This is achieved using the git commit command.

So to summarize, writing code is similar to manufacturing a product. Writing a bloc of code is similar to shipping a couple of products, and creating a commit means then putting the shipped products into a container.

The commit is then initially created on the computer, so locally. The coder can decide de send that commit to the remote hoster repository using the command git push .

One important thing to note about commit creation is that Git associates a unique identifier, often called a hash or Sha, with each created commit.

What makes commits so powerful are two primary advantages:

  • The first advantage of commits is surgical error management. Coders are human, so an error can quickly occur. If a coder realizes an error, he can identify the commit in which the code causing the error is located and remove it. If this code is part of the latest modifications and hasn't been committed yet, the coder can use the git stash command to kind of move all the last modifications into a temporary trash and he can restore the changes using git stash pop , if he notices it was also an error to stash all the las changes 😅. If a commit has already been created using the erroneous code, he can use the git reset command to revert the codebase to the state before that commit. Alternatively, he can use the git revert command, which creates a new commit with changes to undo the erroneous commit's changes. The coder can also employ the iterative command git rebase , which allows him to target any commit in the history. Now, if the solution is not to remove the commit but to modify it, the coder can simply create a branch from that commit using git commit hash-of-the-commit, make the necessary modifications, and then use the git commit --amend command to override that commit with the corrections.
  • The second advantage is reusability. Commits can be merged using git rebase with disconcerting flexibility. Commits can also be reused with the git cherry-pick command. For example, if the coder 2, in the implementation of his feature, realizes he need a specific sub-feature that coder 1 has already implemented on his own branch, the coder 2 can use the git cherry-pick command to apply only the changes related to that small sub-feature into his own branch and continue working. This is incredibly powerful. Yes, I can never be tired of using the word powerful talking about GIT .

Git has many other uses that make it a powerful surgical-level tool.

Now, let's assume that the first coder finishes first. In this case, he will merge his branch, named feature-1, into the main branch, which initially only contains essential base files. There are two methods to accomplish this:

  • The first method is to do it via the command line with the git merge feature-1 command.
  • The second method is to do it on the web interface of the Git hosting service. He first needs to create a merge request , also known as a pull request depending on the hosting platform. Then, he can click the merge button.

In general, merging a branch into the main branch involves many other steps, such as code review, but this is not the subject of this content.

So, at this stage, the main branch contains the code for the first feature.

Later on, the second coder also finishes his feature-2 and wishes to merge his code into the main branch. However, because he created his branch from the main branch, the main branch didn’t yet contain the code for feature 1. So, his local version of the main branch is behind the current state of the main branch in the remote repository. Therefore, he first needs to update it before he can merge. To do this:

  • He first needs to switch to his local copy of the main branch, since he is currently on the feature-2 branch by executing the command git checkout main or git checkout master.
  • Then he executes the command git pull to update his local copy of the main branch.

But now, his own branch, the one for feature-2, is also not up to date with the main branch since it was created from the original version that didn't contain feature-1. So, before he can merge his code into the up-to-date main branch, he must first update his own branch with the main branch, meaning applying all the changes that have occurred in the main branch from the moment he created his branch from the main branch to the moment he wants to merge his branch into it. In our case, the only change made was the addition of feature-1 code by the first coder.

Git permits this update by simply executing the git rebase command. More precisely, the coder2 returns back to his feature2 branch and executes git rebase main .

But again there could be another problem while executing that command.

Let’s suppose that, to implement feature-1, the first coder had to modify a part of the base files that were added at the repository creation into the main branch. Let’s also suppose that the second coder has also modified the same part of the base files during his implementation of feature-2.
The poor GIT, no matter how powerful it is, has no way of knowing which modification to keep or discard, and this leads to a key git concept that can easily give programmers nightmares 😭: conflicts 😬. This is similar to multiple people trying to edit the same line of a Google Doc document simultaneously.

To help the second coder resolve this conflict, Git typically offers three automatic options:

  • The first option is to keep the modifications from the main branch, i.e., the changes made by the first coder.
  • The second option is to Keep his own modifications.
  • The third one is to keep both modifications.

Coder 2 must think carefully to take the right action, the one that will allow feature 2 to function correctly while ensuring that all the other features on the main branch continue to work normally.

In some cases one of these 3options is sufficient, but in many cases, it’s not the case, and Coder 2 will have to rewrite the modifications himself.

Once the conflict is resolved, Coder 2 can finally merge his branch into the main branch.

Another aspect that consistently makes Git so powerful is the concept of sub-modules.

Sub-modules allow a codere to virtually add another Git repository into his own repository by including a reference to that other repository without manually adding all the code of that repository. Again, this is powerful 😁.

We have reached the end of this article. Thank you for reading, and I'll see you in the next one.

Top comments (0)