If you're going to learn one skill that will define your career as a software developer, make it Git.
Git is more than just a tool for tracking files; it's the shared language of collaboration, the safety net for experimentation, and the absolute bedrock of modern software engineering.
Getting good at Git means learning the core commands, sure, but it also means understanding how to use branches to build features without breaking things and how to work with a team using remote repositories like GitHub. Honestly, it’s the most important thing you can have in your toolkit.
Before we dive into the commands, let's get one thing straight: Git isn't just another program to learn. It's the backbone of how we build software today.
Think of it as a time machine for your code. It gives you the confidence to try out a wild new idea, knowing you can always rewind to a stable version with a single command if it all goes wrong. This freedom to experiment without fear is what fuels real innovation.
Without version control, you're stuck in a nightmare of folders named project_final, project_final_v2, and my personal favorite, project_really_final_i_swear. We’ve all been there. Git saves you from that chaos by giving you a clear, searchable history of your project. Who made this change? Why was it added? What did the code look like last Tuesday? Git has the answers.
What really makes Git special is its distributed nature. Older systems were centralized, meaning everyone worked off a single, shared server. That created a huge bottleneck and a single point of failure. If the server went down, everyone stopped working.
Git flips that model on its head. Every developer has a complete copy of the project's history on their own machine.
This completely changes the way teams work. You can code on a plane, commit your changes locally, and then sync up with your team once you're back online. It’s fast, resilient, and works just as well for a two-person startup as it does for a massive enterprise.
Here’s a quick summary of the fundamental concepts we'll cover, giving you a mental map for the journey ahead.
| Concept | What It Does | Why It Matters |
|---|---|---|
| Repository (Repo) | A project's folder containing all files and their entire version history. | This is your project's "database" of changes. |
| Commit | A snapshot of your files at a specific point in time. | Think of it as a "save point" with a descriptive message. |
| Branch | An independent line of development within a repository. | Lets you work on new features or fixes without disturbing the main codebase. |
| Merge | The act of combining changes from different branches into one. | How you integrate a new feature back into the main project. |
| Remote (e.g., GitHub) | A version of your repository hosted on a server, accessible to your team. | The central hub for collaboration, sharing code, and managing projects. |
These concepts are the building blocks of every Git workflow, from a solo project to a team of hundreds.
Let's say you're building a Django Ninja API for your portfolio. You introduce a bug that breaks everything. How do you roll back your work without losing the last three hours of progress? That's where your Git commit history becomes your best friend.
It's no surprise that Git absolutely dominates the industry, with an incredible 93.87% of version control usage worldwide. The benefits are proven at the highest levels. Jaguar Land Rover, for example, cut their feedback cycles by 99% by adopting GitLab, allowing them to deploy code up to 70 times per day.
And as AI agents start authoring millions of pull requests, a clean, well-maintained Git history is what will separate the amateurs from the professionals.
For anyone serious about a career in software, Git proficiency is non-negotiable. Whether you're building portfolio projects or contributing to open source, your GitHub profile acts as a public resume. It shows employers not just what you can build, but how you build—methodically, cleanly, and collaboratively. If you're building out your skills, our guide on how to become a backend developer is a great place to continue your journey.
Alright, before we can dive into tracking changes and building that impressive commit history, we need to get Git set up on your machine. Think of this as the one-time-only rite of passage that every developer goes through. It’s a straightforward process, no matter if you're on Windows, macOS, or Linux.
Let's get your environment ready.
Installing Git unlocks a whole new world of version control. Each operating system has a slightly different, but very simple, installation path.
Windows: The easiest route is to grab the official installer directly from the Git for Windows website. Just run the .exe file and click through the prompts. Seriously, the default options are perfect for 99% of users, so don't overthink it.
macOS: Good news—you might already have it. Pop open your terminal and type git --version. If it's not there, your Mac will usually offer to install the Xcode Command Line Tools for you, which bundles Git. Alternatively, if you use Homebrew, you can just run brew install git.
Linux (Debian/Ubuntu): It doesn't get much simpler than this. Open a terminal and run sudo apt-get install git. And you're done.
Once that's finished, pop open your terminal or command prompt and run git --version. If you see something like git version 2.43.0 pop up, you're officially in business.
While there are plenty of slick graphical clients for Git, getting comfortable with the command-line interface (CLI) is a career-defining skill. It's the universal language of Git, and it’s what you’ll see used in most professional environments. If the terminal feels a bit intimidating, our guide on mastering Linux terminals will get you up to speed quickly.
With Git installed, there are two crucial settings you need to configure right away. These commands tell Git who you are, attaching your name and email to every single commit you make. This isn't just for neat bookkeeping; it's fundamental to how platforms like GitHub track contributions.
Why This Matters: Imagine a team project where commits are just attributed to "admin" or some generic system user. It's chaos. You can't tell who changed what or why. Properly setting your Git identity ensures your work is always credited to you, which is essential for collaboration and building your professional portfolio.
Open your terminal and run these two commands, swapping in your own details:
git config --global user.name "Your Name" git config --global user.email "[email protected]"
That --global flag is key. It tells Git to apply these settings to every project on your computer, so you only have to do this once.
And that's it! With your environment configured, you’re ready to initialize your first repository and start to truly how to use Git for version control.
Alright, you've got Git installed and configured. Now what? This is where the rubber meets the road. We're moving from setup to the handful of core commands that will become second nature, the ones you'll type dozens of times a day without even thinking.
Let's say you're kicking off a new portfolio project. You've made a fresh folder called portfolio-project. Right now, it's just a plain old folder. Git has no idea it exists.
Let's fix that. Open your terminal, navigate into that folder, and run your very first Git command.
git init
That’s it. This one command instantly turns that directory into a Git repository (or "repo" for short). It creates a hidden .git folder inside, which is the brains of the operation. This is where Git will track every single change you make from here on out. Your project is now officially under version control.
Before you start saving work, you need to understand a fundamental concept: Git's three file states. Every file in your project is always in one of these states, and your job is to move files through this workflow.
.git directory.Think of it like this: you write some code (modified), you review it and decide it's ready (staged), and then you save it with a descriptive message (committed). This little dance is the heart of the Git workflow.
Let's see it in practice. Create a new index.html file in your project. Now, run the single most useful command in your entire Git toolkit:
git status
Git will tell you that you have an "untracked file." It sees index.html but isn't watching it yet. Our next job is to tell Git to start tracking it.
To move a file from "untracked" or "modified" into the "staged" state, you use the git add command. This tells Git, "Hey, I want to include the current version of this file in my next snapshot."
git add index.html
Run git status again. Notice the difference? The file is now under a new heading: "Changes to be committed." This is the staging area—your collection of ready-to-go changes.
A pro tip: You'll often see developers use
git add .to stage every new and modified file in the current directory. It's a huge time-saver, but use it with caution. Always rungit statusfirst to make sure you're not accidentally staging log files or other junk you don't want in your history.
Once you're happy with what's in your staging area, it's time to create that permanent snapshot with git commit. This command takes everything that's staged and saves it to your project history, complete with a message explaining what you did.
git commit -m "Initial commit: Add index.html"
The -m flag lets you add your commit message right from the command line. A good commit message is a lifesaver. Keep them short, clear, and written in the present tense (e.g., "Add user login feature" instead of "Added the feature"). Your index.html file is now safely logged in your repo's history.
As your project gets bigger, you’ll inevitably need to look back at what changed, when, and by whom. The git log command is your time machine.
Running git log shows you a complete history of every commit. You'll see the unique ID for each commit (a SHA hash), the author, the date, and the commit message you wrote. This is the official story of your project's life.
But what if you want to see the content of your changes before you even commit them? That's where git diff comes in. If you make another change to index.html but haven't staged it yet, git diff will show you exactly which lines were added or removed. It's the perfect way to double-check your work before you save it.
If commits are your project’s save points, then branches are the alternate timelines where you can experiment without fear. Branching is, without a doubt, Git’s most powerful feature. It allows you to build a new feature, fix a bug, or just try out a wild idea in a completely isolated space.
You can make a total mess, break things, and explore—and none of it will touch your stable, working codebase until you’re absolutely ready.
Think of your main line of work—usually called main or master—as the trunk of a tree. When you create a branch, you’re growing a new limb. You can work on this new limb, adding your code (leaves and flowers), with zero risk of damaging the trunk.
This workflow is absolutely fundamental to using Git in any team setting. It’s what prevents the chaos of everyone pushing changes directly to the main codebase, a recipe for constant bugs and a very unstable project.
Let's walk through the most common reason you'll create a branch: building a new feature. Imagine you’ve been tasked with adding a "Contact Us" page to your company’s website. The last thing you want to do is build this directly on the main branch where live traffic might be running.
So, the first thing you do is create a new branch. It’s a good practice to give it a descriptive name. A common convention is something like feature/contact-page. To create and switch to this new branch in a single command, you'll use git checkout with the -b flag.
git checkout -b feature/contact-page
This handy command is actually a shortcut for two separate actions: git branch feature/contact-page (which creates the branch) and git checkout feature/contact-page (which switches your working directory to it). You're now in your own isolated sandbox.
Now you can get to work. Create your contact.html file, add your styling, and commit your changes just like you normally would.
git add .
git commit -m "feat: Add initial structure for contact page"
Your work is now safely recorded on the feature/contact-page branch, completely separate from main. Every time you make changes, you're following the same fundamental Git rhythm.
This simple process—modify, stage, and commit—is the core loop of Git. You'll do this over and over, no matter which branch you’re on.
Once your shiny new contact page is finished and tested, it’s time to bring it into the main project. This is the moment of integration. First, switch back to the main branch.
git checkout main
Then, you’ll use the git merge command, telling it the name of the branch you want to pull changes from.
git merge feature/contact-page
If there are no conflicting changes, Git will perform a "fast-forward" merge. It simply takes the commits from your feature branch and stacks them right on top of main. Just like that, your contact page is live!
As you get more comfortable with branching, you'll find yourself using a core set of commands over and over. This table is a quick reference for the ones you'll use most.
| Command | Description | Example Usage |
|---|---|---|
git branch <branch-name> |
Creates a new branch. | git branch fix/login-bug |
git checkout <branch-name> |
Switches to an existing branch. | git checkout fix/login-bug |
git checkout -b <branch-name> |
Creates a new branch and switches to it. | git checkout -b docs/update-readme |
git branch |
Lists all local branches. | git branch |
git branch -d <branch-name> |
Deletes a local branch (safely). | git branch -d feature/contact-page |
git merge <branch-name> |
Merges the specified branch into the current one. | git merge fix/login-bug |
These commands are the bread and butter of daily Git work. Mastering them is key to managing your project's history effectively.
Sooner or later, it’s going to happen. You’ll try to merge a branch and Git will stop you with a message: MERGE CONFLICT. It sounds way scarier than it actually is.
A conflict simply happens when you try to merge two branches that have made competing changes. For example, maybe you and a teammate both edited the very same line in your styles.css file. Git has no way of knowing which change is the "correct" one, so it pauses the merge and asks you, the human, to step in and make the decision.
A merge conflict is not an error message. It's a normal, expected part of working on a team. Learning to resolve them calmly is a key skill that separates a Git novice from a confident developer.
When a conflict hits, Git will tell you exactly which files have issues. If you open one of those files in your editor, you’ll see some strange markers that Git has added:
<<<<<<< HEAD
This is the line from your current branch (e.g., main).
=======
This is the conflicting line from the other branch (e.g., feature/contact-page).
> > > > > > > feature/contact-page
Your job is straightforward:
<<<<<<<, =======, and >>>>>>>) so the file looks exactly how you want it to.You do this by staging the file you just fixed and then completing the commit.
git add conflicted-file.html
git commit
Git will often pre-populate a commit message for you, something like "Merge branch 'feature/contact-page'". Just save that message, and you’re done. The conflict is resolved, the merge is complete, and you've successfully navigated one of the most common hurdles in version control.
So far, you’ve been the sole master of your local repository. But the real power of Git is unlocked when you start working with others. This is where remote repositories, hosted on platforms like GitHub, enter the picture.
Think of it this way: your local repository is your private workshop. A remote is a version of that workshop that lives on a server, acting as a shared showroom and assembly line for you and your team. Connecting the two is how modern software actually gets built.
Let's say you've just created a new, empty repository on GitHub named portfolio-api. GitHub helpfully gives you a URL for this new remote repo. Now, you just need to tell your local Git project where to find it.
Back in your local project’s terminal, you'll use the git remote add command. This command simply creates a named link between your local repo and the one on GitHub. By convention, this primary remote connection is almost always named origin.
git remote add origin <YOUR_GITHUB_REPO_URL>
You've now got a handy shortcut (origin) that points directly to your GitHub repository's URL. You can double-check that it's set up correctly by running git remote -v, which will show you the URLs for fetching (downloading) and pushing (uploading).
With the connection made, it's time to share your work. The git push command is how you send your committed changes from your local machine up to the remote on GitHub.
The very first time you push, you need to be explicit. You have to tell Git which remote to send your code to (origin) and which local branch you're pushing (main). The -u flag is important here; it sets up a tracking relationship so future pushes from this branch are much simpler.
git push -u origin main
After this initial command, any time you want to send new commits from your main branch, you can just run git push. Simple as that. Your work is now safely backed up on GitHub and visible to anyone you're collaborating with.
Collaboration is a two-way street. While you're working, your teammates might be pushing their own changes to the remote. To keep your local copy from getting stale, you need to sync up. Git gives you two main commands for this: git pull and git fetch.
git fetch is the cautious approach. It downloads all the new data from the remote but doesn't automatically merge it into your working files. It just gives you a chance to see what's changed.
git pull is more direct. It's basically a git fetch followed immediately by a git merge. It grabs the new changes and instantly tries to integrate them into your current branch.
My personal workflow tip: I almost always use
git fetchfirst. This lets me review the incoming changes withgit log origin/mainbefore I decide how to merge them. It prevents surprises and gives me way more control, especially on a busy project.
For those looking to go deeper into these collaborative workflows, our comprehensive course on Git and GitHub covers these concepts with plenty of hands-on exercises.
Just pushing and pulling changes is fine for a solo project, but on a team, you need a process for code review. This is what Pull Requests (PRs) are for. A Pull Request is a formal proposal to merge your changes from a feature branch (like feature/contact-page) into a main branch (like main).
It’s the heart of collaboration on GitHub. A PR opens up a discussion forum right alongside your code. Teammates can review your work, leave comments on specific lines, suggest improvements, and ultimately approve the merge. This whole process is crucial for ensuring code quality and keeping the team on the same page.
Today, this process is getting even smarter. Pull requests are a collaboration superpower, and with tools like Copilot Chat making code reviews 15% faster, the workflow is more efficient than ever. In an ecosystem where Git powers 93.87% of all version control and AI agents are contributing over 1 million PRs, mastering the PR workflow is non-negotiable.
For developers switching careers, a strong GitHub portfolio filled with well-documented PRs is a huge signal to recruiters. It’s no wonder that over 50% of developers who try Copilot stick with it. You can discover more insights about these game-changing GitHub trends.
As you start to get the hang of Git, you'll inevitably hit a few snags. Certain questions pop up over and over again for developers learning the ropes. This section dives into those common sticking points with clear, practical answers to get you unstuck and moving forward.
This is probably the number one point of confusion for newcomers, but the distinction is pretty straightforward once you see it. Think of it this way: Git is the engine, while GitHub is the car and the entire highway system combined.
Git is the actual version control system itself—it’s a command-line tool you install and run on your machine. It’s what tracks your file changes, manages your history, and lets you branch and merge. You could use Git all day long on your own computer without ever connecting to the internet. It works completely offline.
GitHub, on the other hand, is a web platform built on top of Git. It's a service where you can store your Git repositories in the cloud. More importantly, it adds a whole collaborative layer that Git alone doesn't provide.
In short: Git is the tool. GitHub is the service that hosts your Git projects and makes teamwork possible.
We’ve all been there. You commit, then immediately realize you made a mistake. Thankfully, Git gives you a few ways to turn back the clock. The right method depends entirely on whether you’ve already shared that commit with your team by pushing it to a remote repository.
If the commit only exists on your local machine (you haven't pushed it), you have two main options:
git reset --soft HEAD~1: This is my go-to. It's perfect for when you forgot to add a file or just want to re-word the commit message. It undoes the commit but keeps all your changed files staged and ready. Your work is safe; you just get a do-over on the commit itself.git reset --hard HEAD~1: Use this one with extreme caution. This command doesn't just undo the commit—it completely obliterates it and all the changes you made. It’s a permanent deletion. Only use this if you are 100% certain you want to throw that work away forever.If you have already pushed the commit, you should never use git reset. Rewriting history that others have already pulled down will create a massive headache for your team. The professional and safe way to handle this is with git revert.
git revert <commit-hash>
This command doesn't delete anything. Instead, it creates a brand new commit that does the exact opposite of the commit you want to undo. This keeps the project history clean, linear, and accurate, showing everyone that a change was made and then intentionally reversed.
A great commit message is a gift to your future self and your teammates. It transforms your Git log from a messy, confusing list into a searchable, valuable story of your project's life.
The most effective convention is a simple one. The subject line should be a short summary of 50 characters or less, written in the imperative mood—as if you're giving a command to the codebase.
Add user authentication endpointadded the user stuffFixing a bugIf you need to add more context, leave a blank line after the subject and write a body. The body should explain the what and the why, not the how. The code itself already shows the how.
Example of a great commit message:
feat: Implement rate limiting for API requests
Adds a token bucket algorithm to limit unauthenticated users to 100 requests per hour.
This prevents potential abuse and ensures service stability during traffic spikes. Resolves issue #42.
Writing clear messages like this is a fundamental skill. It makes it easy for anyone to understand the project’s evolution at a glance.
Absolutely! There’s no prize for doing everything in the terminal. Many experienced developers use a hybrid approach, and you shouldn't feel any shame in reaching for a GUI.
Graphical clients like Sourcetree, GitKraken, or the built-in Git tools in VS Code are fantastic for certain jobs. They really shine when you need to visualize a complex branch history—seeing a graphical tree can instantly clarify how different lines of work relate. They are also often much better for resolving tricky merge conflicts, giving you a side-by-side view that makes it easier to pick and choose changes.
However, I strongly urge every developer to become proficient with the command line first. The command-line interface (CLI) is the bedrock of Git. It’s universal, it’s available everywhere, and it’s often much faster for day-to-day tasks like adding, committing, and pushing. More importantly, you need CLI skills for any kind of automation, scripting, or setting up CI/CD pipelines.
A great workflow is to use the CLI for your frequent, muscle-memory commands and then switch over to a GUI for more visual or complex operations like an interactive rebase or untangling a gnarly merge.
Ready to build the real-world skills that get you hired? Codeling offers a hands-on Python curriculum designed to turn you into a job-ready backend engineer. You'll build portfolio-ready applications, master Git and GitHub, and learn to design production-grade APIs. Try our interactive platform and start coding from day one at https://codeling.dev.