logo Fonnpo

Contact Me
May 30, 2026 3 min read Fonnpo

The Complete Git Guide

Git is the most widely used version control system. This guide covers initial setup, basic workflow, branch management, merging and rebasing, remote repositories, stash, undoing changes, tags, .gitignore, Fork collaboration workflow, and common troubleshooting — everything you need for day-to-day development in one place.

#Git#DevOps#SSH

Git is the most widely used version control system today. This guide starts from initial setup and covers the vast majority of operations you will use in daily development — branches, merging, rebasing, undoing changes, stash, collaboration workflows, and more.

Initial Setup

Configure Git before using it for the first time:

Bash
        git config --global user.name "Your Name"
git config --global user.email "you@example.com"

    

Set the default branch name (recommended: main):

Bash
        git config --global init.defaultBranch main

    

Set the default editor (VS Code example):

Bash
        git config --global core.editor "code --wait"

    

View all configuration:

Bash
        git config --list

    

Creating a Repository

From scratch:

Bash
        mkdir my-project && cd my-project
git init

    

Clone an existing repository:

Bash
        # HTTPS (requires username/password or token)
git clone https://github.com/user/repo.git

# SSH (requires SSH key setup)
git clone git@github.com:user/repo.git

# Clone into a specific folder name
git clone git@github.com:user/repo.git my-folder

    

Basic Workflow

Git has three local layers: working directory → staging area → local repository.

Bash
        # Check current status
git status

# Add files to staging
git add file.txt
git add .          # stage all changes
git add -p         # interactively stage chunks (very useful)

# Commit
git commit -m "feat: add user login"

# Skip staging, commit tracked changes directly
git commit -am "fix: correct typo"

    

Commit Message Convention (Conventional Commits)

Good commit messages make history readable and enable automatic CHANGELOG generation:

Properties
        type(scope): subject

feat     New feature
fix      Bug fix
docs     Documentation change
style    Formatting (no logic change)
refactor Code refactor
test     Add or modify tests
chore    Build process, tool config, etc.

    

Viewing History

Bash
        # View commit history
git log

# Compact one-line format
git log --oneline

# Graphical branch view
git log --oneline --graph --all

# View history of a specific file
git log --follow -- path/to/file

# View changes of a specific commit
git show <commit-hash>

    

Branch Management

Branching is one of Git's most powerful features — nearly free to create and switch.

Bash
        # List all branches
git branch
git branch -a   # including remote branches

# Create a new branch
git branch feature/login

# Switch to a branch
git switch feature/login

# Create and switch in one step (common shorthand)
git switch -c feature/login

# Delete a branch
git branch -d feature/login    # safe delete (warns if unmerged)
git branch -D feature/login    # force delete

# Rename current branch
git branch -m new-name

    

Merging

Bash
        # Switch to the target branch (usually main)
git switch main

# Merge the feature branch
git merge feature/login

    

Fast-forward merge: the target branch has no new commits, so Git simply moves the pointer forward — history stays linear.

Non-fast-forward merge: the target has new commits, so Git creates a merge commit and history shows the fork structure.

To always create a merge commit (preserving the branch record):

Bash
        git merge --no-ff feature/login

    

Resolving Conflicts

When a merge conflict occurs, the affected file contains markers:

Bash
        <<<<<<< HEAD
your local content
=======
incoming content
>>>>>>> feature/login

    

Manually edit the file to keep the correct content, then:

Bash
        git add .
git commit    # Git auto-fills the merge commit message

    

Rebasing

Rebase replays your branch's commits on top of another branch, keeping history linear and clean.

Bash
        # On the feature branch, rebase it onto the latest main
git switch feature/login
git rebase main

    

Interactive rebase (great for cleaning up commit history):

Bash
        # Edit the last 3 commits
git rebase -i HEAD~3

    

Available commands in the editor:

CommandEffect
pickKeep the commit as-is
rewordKeep but edit the message
squashCombine into the previous commit
fixupLike squash, discard the message
dropDelete the commit

Note: Never rebase commits that have already been pushed to a shared public branch — it rewrites history and causes conflicts for others.

Remote Repositories

Bash
        # View remotes
git remote -v

# Add a remote
git remote add origin git@github.com:user/repo.git

# Change remote URL
git remote set-url origin git@github.com:user/new-repo.git

# Push (use -u the first time to set upstream)
git push -u origin main

# Subsequent pushes
git push

# Pull (fetch + merge)
git pull

# Fetch only, without merging
git fetch origin

# Delete a remote branch
git push origin --delete feature/login

    

Stash

When you need to switch branches but have uncommitted changes you are not ready to commit:

Bash
        # Stash current changes
git stash

# Stash with a description
git stash push -m "wip: half-done login form"

# List all stashes
git stash list

# Restore the most recent stash (keep it in the list)
git stash apply

# Restore and remove from list
git stash pop

# Restore a specific stash
git stash apply stash@{2}

# Delete a specific stash
git stash drop stash@{0}

# Clear all stashes
git stash clear

    

Undoing Changes

Git has several undo commands — understand them by scenario:

Undo working directory changes (before add)

Bash
        # Restore a file to its last committed state
git restore file.txt

# Restore all files
git restore .

    

Unstage files (after add, before commit)

Bash
        git restore --staged file.txt

    

Amend the last commit

Bash
        # Edit the commit message, or add a forgotten file
git add forgotten-file.txt
git commit --amend

    

Safely undo a commit (creates a reverse commit)

Bash
        git revert <commit-hash>

    

Roll back to a previous commit (reset)

Bash
        # Soft reset: undo the commit, keep changes in staging
git reset --soft HEAD~1

# Mixed reset (default): undo the commit, move changes to working dir
git reset HEAD~1

# Hard reset: discard the commit and all changes (destructive, use carefully)
git reset --hard HEAD~1

    

revert vs reset:

  • revert appends a new commit that reverses changes; history is preserved — safe for public branches
  • reset rewrites history — only use it on local commits that have not been pushed

Tags

Typically used to mark release versions:

Bash
        # Lightweight tag
git tag v1.0.0

# Annotated tag (includes a message)
git tag -a v1.0.0 -m "Release version 1.0.0"

# List all tags
git tag

# Push a tag to remote
git push origin v1.0.0
git push origin --tags   # push all tags

# Delete a tag
git tag -d v1.0.0
git push origin --delete v1.0.0   # delete remote tag

    

.gitignore

.gitignore tells Git which files to leave untracked:

Properties
        # Dependencies
node_modules/
vendor/

# Build output
dist/
build/
*.min.js

# Environment variables
.env
.env.local

# OS files
.DS_Store
Thumbs.db

# IDE config
.vscode/
.idea/

    

Files already tracked by Git are not ignored just by adding them to .gitignore — you need to untrack them first:

Bash
        git rm --cached file.txt          # untrack a single file
git rm --cached -r node_modules/  # untrack a directory

    

Collaboration Scenarios

Fork + Pull Request Workflow

  1. Fork the target repository to your account
  2. Clone your fork
  3. Create a feature branch
  4. Develop and commit
  5. Push to your fork
  6. Open a Pull Request / Merge Request on GitHub / GitLab

Keep your fork in sync with upstream:

Bash
        # Add upstream remote
git remote add upstream git@github.com:original/repo.git

# Fetch upstream changes
git fetch upstream

# Merge into local main
git switch main
git merge upstream/main

    

Key Principles for Team Collaboration

  • main / master is usually protected — no direct push allowed
  • Open one feature branch per feature
  • Rebase onto the latest main before merging to reduce conflicts
  • Do Code Review in PRs before merging

Handy Commands

Bash
        # Compare two branches
git diff main feature/login

# Show who changed each line of a file
git blame file.txt

# Binary search for the commit that introduced a bug
git bisect start
git bisect bad            # current version is broken
git bisect good v1.0.0    # this version was fine
# Git checks out the midpoint — test it, then mark good or bad
git bisect reset          # finish

# Apply a specific commit to the current branch
git cherry-pick <commit-hash>

# Remove untracked files and directories
git clean -fd

    

Common Issues

Push rejected

Usually because the remote has new commits from others:

Bash
        git pull --rebase   # pull then rebase, keeps linear history
git push

    

Recovering a deleted branch

Commits do not disappear immediately. Find them via reflog:

Bash
        git reflog              # view all operation history
git switch -c recovered-branch <commit-hash>

    

Large file accidentally committed

Large files should not live in Git (they permanently bloat the repository).

If not yet pushed:

Bash
        git rm --cached bigfile.zip
git commit --amend

    

If already pushed, use git filter-repo (replacement for the deprecated filter-branch) to purge the file from history — the process is involved, so the best fix is preventing it upfront with .gitignore.

Fonnpo