Written By:
Nestor Rubio
Last Updated:
May 6, 2024
The safest and smartest way to explore anything in many free-roam games is to find a good spot just before you embark on your risky adventure and select that as your save spot. Whether saving in current save file or opening a new one. This has all the benefits of allowing you to proceed with your risky journey and possibly reaping all the benefits while also knowing all your progress is safe and sound. There’s something similar available to us in our coding journeys and it can be found in Git. Keep reading to see why this metaphor is not misplaced.
What is Git?
Git is a distributed version control system that is widely used in the world of software development. It allows multiple programmers to collaborate on a project efficiently and with the assurance that if anything goes wrong a rollback version is always available. This can be achieved by providing a history of changes and document file versions, allowing developers to create branches to work on different features or fixes simultaneously, and later merge these changes seamlessly and even allowing developers to push and pull changes to and from a central repository. Overall, Git makes code management a simpler and safer process.
More can be found on the official website of Git.
NOTE: Git is separate from GitHub, despite what your “all-knowing” peers may try to tell you. Git is the system used to track changes while GitHub is simply the biggest web-based platform for hosting those Git-based projects or “repositories” as they are called.
Why Use Git?
As hinted to in the introduction to this post, Git can serve as a metaphorical save point for your coding. It would be a shame if you started working on a cool new feature for your project, things fell apart, and you had no way to undo those changes. When working solo on a project, the extent of Git is simply keeping a history stored so that you can always go back to a stable version. This changes when you start working in a collaborative setting.
When a project needs multiple people working on it, imagining another way can be tough. Without a centralized code base that everyone can see the latest version of, you may have to resort to sending all updated files to one another or even be forced to limit how much work is done as to diminish how disconnected everyone’s documents can become. There’s a reason it is so in demand when it comes to the software engineering workforce.
This is achieved in part, through Git’s three-tier process of keeping versions of documents in history. First, the working directory. This is what we would see as our directory without Git at all. It’s where all your work is done, your saves get stored, and no real version control has happened yet. Next, there is the staged tier, which is what happens when you’ve “staged” your changes. This is essentially notifying your Git environment that some changes have been made and you’re setting them on the stage to eventually get committed to history. Lastly, comes the committed stage. This is the graduation of your changes and version from simply being staged for storage to having actually been committed in Git history. Full manipulation of this three-tier structure will be elaborated on in the Basic Git Commands section of this post.
Learning Git will not only serve you greatly in your individual and collaborative coding journey through helping complete projects but will also help improve your experience learning by furthering the bounds of how curious you can be. With the safety net of knowing you can always go back to your save spot, you can always try something new and see what comes of it. I recently had to use some charting libraries in React and React Native for my job and explored many charting libraries without having any of them break the code base. In a safe way, I was able to do trial and error on the libraries until I landed on the best ones for the job. I could achieve this with my thorough understanding of Git versioning and awareness that I can play around as much as I want as long as I go back to my save point when I’m ready. This same idea can be extended to individual projects or learning time. Want to try a new package? Rewrite that logic? Fix that bug that has been present for the last three months? Git can help with that!
Also, it feels cool to know a skill like Git, arrive on a job, and immediately start teaching it to those already working there. Been there, done that, felt amazing and really let me start contributing to the team immediately.
How to Use Git?
Installing Git
- Visit the Git website downloads page to look for your OS and begin installation of the Git software installer
- Run the installer, accepting all defaults as they come across
- Accepting the defaults is typical, the options are there for those who know what they are doing but I am assuming we are looking to simply get started with Git
- With Git installed, we can now open a means of accessing the command line interface (CLI) which can come in many forms
- If you wish to use the native Git Bash application that was downloaded in step 2, you can do so by looking for the application and running it
- If you wish to use a different terminal, you may open your terminal of choice
- Confirm you have Git installed and running by typing
git --version
and making sure it actually returns a Git version- Anything relating to ‘git’ not being a valid command or argument means that Git needs to be set up differently to work for your environment. Best way to solve this is to look up different solutions people have tried and see what works best for your situation.
Configuring Git
Having Git installed isn’t all that’s needed to start working with it. There are many aspects of this workspace to edit and make yours, but below are two of the key things needed for your Git setup.
Identity
With Git solving the problem, of tracking versions of work for projects involving any number of contributors, it’s important to know who made what contributions over time. Part of making sure you get your fair credit is associating your environment to you via the identity configurations. They are primarily involving your name and email address and can be configured in the terminal with
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
Checking Configurations
As you grow and learn how to work within your Git environment, it will always be nice to check in on what configurations you have set. They can be checked via the terminal by running
git config --list
This will list out the many configuration settings you have available to you and the settings you have set for each of them. Feel free to explore these in depth as you progress and learn about your Git environment.
Basic Git Commands
So you got your Git environment set up and running beautifully. Now it’s time to read up on the commands that make this tool so powerful and great to know.
Init
The command to start it all, the init command is used to start a Git repository in the directory or folder it was called from. This essentially makes version control and using Git possible on the folder it was called in.
For example, if I am in the documents/code/git_project directory and execute
git init
then I have initialized a Git repository for the documents/code/git_project directory, meaning a hidden subfolder called .git
was created and this hidden subfolder is used to store many operations and structures which make version control as we know it today, to be possible.
Clone
This command is used to create a local copy of a remote repository. Typically found on GitHub, these repositories can be found through a URL which needs to be provided to this Git command to ensure a successful creation. Finding this URL is easy on GitHub because all you need to do is visit the GitHub repository you wish to copy over, click on the “Code” button, and copy the URL shown. Once copied, you can execute the copying of the repository with the following command.
git clone <URL OF REPOSITORY>
When the repository is successfully copied locally, all Git operations can be done automatically. No need to run git init
, or anything like that because the repository gets cloned over with all of its Git information, .git
subfolder included.
Add
This is the command used to move files into the staging tier of Git’s three tier system.
To move one file version into the staging tier, run
git add <name of file/path to file from current directory>
One thing I like doing is when I’ve worked on multiple files in my project and need to just add all modified files into the staging tier, I will navigate to the project’s root folder and run the following:
git add .
The period denotes the current directory and the command is essentially saying “add all modified files in my current directory to the staging area”. This helps boost productivity when looking to modify many files at once.
Commit
The command that acts as the “save” of the Git workflow, this command actively commits all files currently in the staging area and allows you to add a message to describe what the commit is referring to. This is because typically in a good Git workflow, each commit is related to one task, bug fix, feature, or something that is a small part of a bigger project or goal.
Status
One of my most commonly used commands, status allows you to see the current state of your repository. It shows you what has been changed from a high-level view. A general summary like what files have been modified, deleted, and added is shown. On top of this, you get to see what stage they are in. Earlier, we covered things like the stages involved in the Git workflow and now with status, you can see where they are in that workflow. Feel free to modify, delete, and add some files to see how they move after following each command with git status
. I’m guilty of suing it almost like a sanity check to make sure I really know what is going into my commits.
Checkout
The checkout command can help in so many situations and it has helped me greatly to know a couple of them. Nothing feels sweeter than gliding from my start point to my endpoint with ease because I knew all the ways specific commands could help me get the job done.
Switching branches
In common Git workflows, it is most likely that a new addition, fix, or update will be done on a branch that is not necessarily in test or production. This means your codebase could have several versions existing almost simultaneously. Not necessarily in a Schrodinger’s thought experiment way but in a parallel universe kind of way. Checkout offers us a way to visit each existing version with a command as simple as
git checkout <branch_name>
With this, we can see our files get updated to match the state saved on that branch, effectively taking us to that point and being able to work from there.
Creating a new branch
If you thought the power of switching between versions of code was nice, imagine the power of creating those parallel existences.
The first step is to make sure you are on the branch you want the other one to use as a starting state. This essentially means if you have a stable version on branch main and want to add a feature in which you interact with images, you need to make sure you are on the desired branch with
git branch --show-current
If you are not on main you can put learned checkout command to the test with a switch to it with
git checkout main
Once on main, we are on the branch that can act as the source for the images branch. From here we can create a new branch off of it in which we can add our images implementation. My preferred way is
git checkout -b images
This will create a new branch named images using main as the beginning state of it. From here, you can begin your work and committing your changes without fear of braking the stable version found in main.
Switching to a specific committed version of the code
Checkout’s application extends beyond dealing with branches and can actually be used to go back in time on the parallel universe your on. Read the following section on git log
to see how this combination can be used to revert to a stable version or even used to debug a problem introduced in the past to the codebase.
Log
Curious about the history of your repository and all of the contributions made to it over time? This command is here to help! Running git log
will provide you a view of all the individual commits made to the repository including things like commit date, message, hash, and who made the commit. One of my most common uses for this is if something ends up being broken but was working originally, it would be nice to know which commit broke it and using git log
helps me track down the version I’m looking for to see what caused the feature to break. I typically use this in conjunction with git checkout
by running something like
git checkout <desired hash>
to get the working or broken version and begin debugging from there. This has been very handy especially when working in a codebase in which there are more than a couple of contributors since one person typically can’t track everyone’s contributions in detail.
Merge
Ready to combine a feature in with a stable version or another branch that is in development? Sounds like we’ve reached the right case to use git merge
!
When learning how to use git merge
, it helped me to view this as a process between a source branch which has the thing(s) I want to add and the destination branch which is the branch I want to introduce those new things to.
Continuing the example of the images branch, we can see that introducing our work on the images branch to the main branch is pretty straight forward.
// 1. Make sure I'm on images branch
git branch --show-current
// if I see that I'm on images, I need to switch to main
git checkout main
// once on main, I am on the destination branch and it is now time to merge the new work on images into main
git merge images
Note that this will only merge in committed state. This means that if you have unsaved and uncommitted work in the images branch it will not be merged into main and it can be tough to track a missing section like this down. Be sure to always commit your work before merging between branches.
Push
Perfect, we’ve done everything needed to get to a point where we want to push our code to the source of our codebase. Whether this means it is hosted on something like GitHub, GitLab, or a bare repository hosted on another computer, it is a similar process.
Much like the other commands, you need to make sure you are in the branch you want to push to your source code repository. Once on it, make sure all of the desired changes are committed and you can run
git push
If the branch name does not match one in the hosted repository, it is often told to you via the message you see after running git push
and it will let you create a new branch via a command similar to
git push --set-upstream origin <branch name>
This allows you to create the branch in the origin repository that should match the one you are pushing and will push to that branch. While it’s possible to reconfigure this to point to another branch and different origin, it is not necessarily a common practice. It can lead to complicated workflows and work getting lost which I can say that most people don’t want to happen to them.
Pull
With a hosted repository on another machine or in the cloud, it is always helpful to make sure that the version of the branch you are on remains up to date with what everyone else can see. This becomes an issue in teams of contributors where more than one person could work on a branch or a branch gets someone else’s feature merged into it. These changes aren’t automatically shown to your local code, it is on you to retrieve them. You have to be on the branch you wish to get the local version for in order for this command to run as smoothly as possible on your end. This command not only retrieves those changes but also merges them into your repository so that this merge from pull is also visible in your commit history and can be tracked accordingly. Pretty neat addition to this functionality! This can be as simple as
git pull
Fetch
This command offers a quick way to get other resources available to the branch. More often than not in my cases this means things like branches that someone else posted that are not yet visible to you locally. I see this as a kind of quick way to view all of those extra commits and branches pushed to the source repository by teammates or fellow contributors. This command can be used with a quick
git fetch
More to Learn
Advanced Git Topics
As the you contribute more and more to codebases which use Git as their version control system, you will run into many issues like rebasing, stashing, squashing, cherry-picking, and more. While these are not covered here, I firmly believe it never hurts to do extra research and figure out how to do many of the things made available to you through the tools you use. Trust me, these are things I didn’t need when I first started to use Git in my codebases but as the problems I needed to solve became more complex, these skills helped my teams and myself a lot.
How Git REALLY Works
If you’re anything like me, you’ll use a tool for a bit and start to wonder how it was made. Questions like: “What went into this?”, “How does it run?”, “How can it keep track of changes over such a long period of time?”, and others will cross your mind. Some exploring lead me to come across a brilliant article titled “How Git truly works: A deep dive on the internals to acknowledge and master Git” by Alberto Prospero who does an amazing job of answering many of these questions. Learning about the inner hashing and storing of commits based on file-based routing and other implementation details helped me get a newfound appreciation for the tool I use everyday in my life as a software engineer.
Conclusion
You are now equipped with many tools required to be proficient in the world of Git contribution. Whether it be for solo projects or working on a team, you can always refer to the commands listed here as well as the tips for when to use them. The best way to truly learn these and become proficient is to challenge yourself to use these commands as often as possible, so go ahead and get coding!
Good luck in your version control journey!