DEV Community

Mohammed Farmaan.
Mohammed Farmaan.

Posted on

Simplifying Git: A Practical Guide for Everyday Use.

This article was originally published on my personal blog on 2025/06/14

Hie! Welcome to another post where I'm going to use my poor writing skills to simplify Git for you, XD.

The Problem

If you're reading this, I expect you to be already familiar with the basic Git workflow. Git is often portrayed as overly complex, which it is but only if you consider all the features it has to offer.

If you only consider the features that you need for everyday software development, it becomes much simpler to use in practice.

Having worked at various companies and multiple personal projects over the years, one thing that has been constant is Git. Your tech stack might change every year or so, but Git remains the same. Learn it once, and you can use it everywhere.

While I'm not an expert, I'll walk you through the most basic Git workflow I use—one that aligns with how most software is written. We'll explore one of the most popular Git workflows, known as Git Flow.

What is Git Flow?

Git Flow is a popular Git branching strategy aimed at simplifying release management, introduced by software developer Vincent Driessen in 2010. Fundamentally, Git Flow involves isolating your work into different types of Git branches - Source.

Git Flow defines specific branch types for different purposes:

  • main/master: Production-ready code.
  • development: Staging/development environments.
  • feature branches: Individual feature development.
  • release branches: Preparing new releases.
  • hotfix branches: Quick fixes to production.

For most projects, you'll primarily work with main (production), development (staging), and feature branches. The others are useful for larger teams with complex release cycles.

📌 Important Note

Before moving forward, I'd like to stop here and define some aliases that make working with Git much easier and fun. Paired with a Zsh framework such as Oh My Zsh, I don't think there is a better way to use Git from a CLI. These aliases are straight from my .zshrc config:

Git CLI

# Navigation & Branch Management alias gb='git branch' # List all local branches alias gc='git checkout' # Switch to an existing branch alias gcb='git checkout -b' # Create and switch to a new branch alias gbd='git branch -d' # Delete a local branch # Push & Pull alias gp='git push' # Push current changes to remote branch alias gpl='git pull' # Pull latest changes from remote branch alias gpo='git pull origin --no-edit' # Pull without opening an editor for merge messages # Commit & Add alias gcm='git commit -m' # Commit with message alias gacp='git add . && git commit -m "uwu" && git push' # Quick add/commit/push with default message. Works best when working on personal projects. # Stash Management alias gs='git stash' # Stash current changes alias gsp='git stash pop' # Apply and remove last stash alias gsl='git stash list' # Show all stashed changes 
Enter fullscreen mode Exit fullscreen mode

GitHub CLI

The GitHub CLI (gh) is GitHub-specific and provides easy integration with GitHub's features like pull requests, issues, and repositories. I use it for both personal projects and professional work.

But the Git CLI should be the same regardless of the code hosting provider you use.

alias gpr='gh pr create --base' # Create a PR by specifying a base branch ex: gpr main alias gpm='gh pr merge' # Merge the current PR (run from the PR branch). 
Enter fullscreen mode Exit fullscreen mode

Now that we have these aliases set up, I'll use them throughout the rest of this article to demonstrate Git workflows. They'll make our examples much cleaner and more practical for real-world usage.

Working with Branches

If you ask me, branches are one of the coolest things about Git. They let you work on features independently without affecting the main codebase.

You can make multiple copies of the same code in multiple branches and test your changes in isolation. Here's how I typically work with branches using the aliases we set above:

Creating, Switching, & Deleting Branches

Always pull the changes from the remote before you create a branch. It will save you a lot of headaches with conflicts later.

# Create and switch to a new feature branch gcb feat/user-authentication # Switch to an existing branch gc feat/user-chat # Delete a local branch after it's been merged, not necessary unless you wanna create a fresh branch with same name. gbd feat/user-authentication # Force delete a local branch (even if not merged - use with caution) gb -D feat/broken-feature # Delete a remote branch gp origin --delete feat/user-authentication 
Enter fullscreen mode Exit fullscreen mode

Adding and Committing

I personally use my editor to add and remove files because it's much easier and gives me a beautiful diff of the changes that I made so that I can be sure that I'm not pushing unintended changes.

The diffs also act as self code review because you can see if you have over-engineered something so you can go back and simplify it. This is far more relevant these days because people are straight up pushing LLM written slop. Please don't be that person.

If you think using the CLI to add files makes you look cool, good luck when you push something to prod without diffing it first.

Nonetheless, here are some examples of adding & removing files using the CLI:

# Add individual files git add src/components/chat.ts git add README.md # Add multiple files git add src/utils/auth.ts src/types/user.ts package.json # Add all files in a directory git add src/components/ # Add all TypeScript files git add *.ts *.tsx # Add everything (use when you're sure you have only changed the required files & make sure to run "git status" to see which files have been modified) git add . # Remove files from staging (if you added by mistake) git reset src/components/chat.ts 
Enter fullscreen mode Exit fullscreen mode

And here's how I typically commit:

# Quick commit for personal projects gacp # Adds everything, commits with "uwu", and pushes # Proper commit with custom message gcm "Add http fallback to websockets" 
Enter fullscreen mode Exit fullscreen mode

Pulling and Pushing

These are the most basic operations to sync your local work with the remote repository. Always pull before you start working to avoid conflicts later.

Note: Git might ask you to configure how to handle divergent branches on your first pull. Just run git config pull.rebase false to use merge (the default). Rebase vs merge is a whole different topic—I just use merge and call it a day.

If you really wanna know how each one differs, you can read it here.

# Pull latest changes from remote gpl # Pull changes from a remote branch gpo main # Push current local changes gp 
Enter fullscreen mode Exit fullscreen mode

Stash Operations

Stash is like a temporary clipboard for your uncommitted changes. Super useful when you need to quickly switch branches but aren't ready to commit yet.

# Save current changes temporarily gs # Restore last stashed changes gsp # See all stashed changes gsl 
Enter fullscreen mode Exit fullscreen mode

Pull Requests (PRs)

PRs are basically how you say "Hey, I made some changes, can you review them?" They're super important for code review and collaboration, especially when working with other people.

These can also be used to keep track of the things that you have shipped.

Creating a PR

After you've pushed your feature branch, creating a PR is dead simple with the GitHub CLI:

gpr main # Creates a PR against the main branch 
Enter fullscreen mode Exit fullscreen mode

The GitHub CLI will ask you for a title and description. Don't just write "fix stuff"—actually explain what you did and why. If not a description, at least make the title clear.

PR Best Practices

I've seen some terrible PRs, so here's what actually matters:

  • Write clear titles: "Add user authentication" not "fix stuff" or "updates."
  • Explain (optional): Don't just say what you changed, explain why you changed it. Not always, but when the changes touch a bunch of other files.
  • Keep PRs Simple: Nobody wants to review 50 files. Break big features into smaller PRs.
  • Test & lint your stuff: Please test & lint your changes ffs before you ask for a review.

Wrapping Up

Alright, that's pretty much everything you need to know about Git for day-to-day development. Honestly, Git can do a lot more than this, but trust me—you as an average developer will barely need that. Here are the takeaways:

  • Git Flow is nice but don't over-complicate it. For small & personal projects, just use main and feature branches.
  • Use aliases. Your fingers will thank you after typing gcb instead of git checkout -b for the 100th time.
  • Branch often. Create branches for everything, even tiny changes.
  • PRs are your friends. They catch bugs and make you and your code better. But only if you take criticism constructively.
  • Commit messages matter when you work with teams. Imagine trying to find the change that broke prod among 100 commits that all say "fixes."
  • When in doubt, stash the changes. It's much better than losing work.

That's about it for this post. See you in the next one! Happy Coding & have a good day!

Top comments (0)