Introduction

Git is the de‑facto version control system for modern software development. Whether you're a solo coder or part of a massive open‑source community, mastering Git can dramatically improve your workflow, collaboration, and code quality. In this post we'll walk through the essentials—cloning, branching, merging, rebasing, and some pro‑level tricks—while keeping the examples short and practical.

1. Getting Started: The First Commit

# Initialize a new repository mkdir my‑project && cd my‑project git init # Create a README and commit it printf "# My Project\n\nA brief description." > README.md git add README.md git commit -m "Initial commit" 

Why git add?

  • Stages files for the next commit.
  • Allows you to commit a subset of changes (useful for partial work).

2. Cloning & Remote Workflows

# Clone an existing repo git clone https://github.com/your‑org/awesome‑app.git cd awesome‑app # List configured remotes git remote -v 

Typical remote names:

  • origin – the default remote created by clone.
  • upstream – a second remote pointing to the original upstream repository (common for forks).

Adding a New Remote

git remote add upstream https://github.com/original/awesome‑app.git 

Now you can fetch upstream changes without affecting your origin branches.

3. Branching: The Core of Parallel Development

# Create and switch to a new feature branch git checkout -b feature/login # Do some work, then commit git add src/login.js git commit -m "Add login component" 

Branch Naming Conventions

  • feature/* – new functionality.
  • bugfix/* – bug repairs.
  • hotfix/* – urgent production patches.
  • release/* – preparation for a release.

Keeping branches short‑lived reduces merge conflicts and simplifies history.

4. Merging vs. Rebasing

Merging (preserves history)

git checkout main git merge feature/login # Creates a merge commit 

Rebasing (linear history)

git checkout feature/login git rebase main # Replay commits on top of main 

When to rebase?

  • Before opening a Pull Request (PR) to keep the PR tidy.
  • Never rebase shared branches that teammates have already pulled.

When to merge?

  • For long‑running branches where you want to retain the original context.

5. Interactive Rebase: Cleaning Up Commits

Suppose you have three messy commits and want to squash them into a single coherent one.

git log --oneline # Identify the commit hash before the three # Assume the hash is abc123 git rebase -i abc123 

An editor opens:

pick e1a2b3 Add login UI pick f4c5d6 Fix login typo pick a7b8c9 Add unit tests 

Change pick to squash (or s) for the second and third lines, save, and edit the combined commit message.

6. Stashing: Save Work in Progress

When you need to switch branches but aren't ready to commit:

git stash push -m "WIP: login UI" # Switch branches, work, then restore git stash list git stash apply stash@{0} 

You can also git stash pop to apply and drop the stash in one step.

7. Resolving Conflicts

A conflict occurs when Git can't automatically merge changes. After a merge or rebase that hits a conflict:

# Open the conflicted file; you'll see markers like: <<<<<<< HEAD // code from current branch ======= // code from incoming branch >>>>>>> feature/login # Edit to keep the correct version, then: git add conflicted-file.js # Continue the operation git merge --continue # or git rebase --continue 

Tip: Use git diff --conflict to see a side‑by‑side view.

8. Tagging Releases

# Annotated tag (recommended for releases) git tag -a v1.0.0 -m "First stable release" # Push tags to remote git push origin v1.0.0 

Annotated tags store the tagger name, email, date, and a message—perfect for release notes.

9. Pro Tips & Lesser‑Known Commands

Command What It Does
git log --graph --oneline --decorate Visualize branch structure in the terminal
git reflog Recover lost commits by viewing the reference log
git cherry-pick <hash> Apply a single commit from another branch
git bisect start … git bisect bad/good Binary search to locate a bug introduction
git filter-branch (or git filter-repo) Rewrite history (e.g., remove large files)

Example: Using git bisect to Find a Bug

# Start bisect on the range where bug appeared git bisect start git bisect bad # Current HEAD is bad git bisect good v1.2.3 # Tag known good version # Git checks out a mid‑point; test, then tell Git: # If bad: git bisect bad # If good: git bisect good # Repeat until Git pinpoints the offending commit 

10. Automating with Hooks

Git hooks let you run scripts at key points. For example, enforce commit messages:

# .git/hooks/commit-msg (make it executable) #!/usr/bin/env bash msg=$(cat "$1") if ! grep -qE "^JIRA-[0-9]+:" <<< "$msg"; then echo "Commit message must start with a JIRA ticket (e.g., JIRA-123: ...)" >&2 exit 1 fi 

Now any git commit that doesn't start with a ticket ID aborts.

Conclusion

Git is a powerful toolbox, not just a single command. By mastering the basics—cloning, branching, merging/rebasing—and sprinkling in advanced techniques like interactive rebasing, bisect, and hooks, you can keep your repository clean, your history readable, and your team productive.

Start applying these patterns today, and watch your development workflow become faster, safer, and far more enjoyable.

Happy coding!