🔀🐙🧠

Git & GitHub — The Developer's Guide

A comprehensive single-page reference covering Git fundamentals, GitHub workflows, and IntelliJ IDEA integration for everyday development.

🔧 Git CLI 🐙 GitHub 🧠 IntelliJ IDEA
View My GitHub
🔧

Git Basics — How It Works

What is Git?

Git is a distributed version control system that tracks changes in your codebase. Every developer has a full copy of the repository, including its entire history. Changes flow through three local areas before reaching the remote.

The Git Data Flow

📁 Working Directory
git add
📋 Staging Area
git commit
💾 Local Repo
git push
☁️ Remote (GitHub)

Working Directory

Your actual project files on disk. This is where you edit code. Files here can be untracked (new) or modified (changed since last commit).

Staging Area (Index)

A holding zone where you prepare changes for the next commit. Use git add to move changes here. Think of it as a "draft" of your next commit.

Local Repository

Your local .git directory containing the full commit history. When you git commit, a snapshot is saved here with a unique SHA hash.

Remote Repository

The shared repository on GitHub (or another host). Use git push to upload and git pull to download changes from the team.

💡
Every commit in Git is identified by a SHA-1 hash (e.g., a1b2c3d). You can always reference any commit by its hash, branch name, or tag.
⌨️

Core Git Commands

Setup & Configuration

Initial setupbash
# Set your identity (required for commits)

git config –global user.name “Your Name”
git config –global user.email “you@example.com”

# Set default branch name
git config –global init.defaultBranch main

# View all config
git config –list

Starting a Repository

Initialize or clonebash
# Create a new local repo

git init

# Clone an existing remote repo
git clone https://github.com/org/repo.git

# Clone into a specific folder
git clone https://github.com/org/repo.git my-folder

Day-to-Day Workflow

Stage, commit, pushbash
# Check status of working directory

git status

# Stage specific files
git add file1.java file2.java

# Stage all changes
git add .

# Commit with a message
git commit -m “feat: add user authentication endpoint”

# Push to remote
git push origin feature/my-branch

# Pull latest changes
git pull origin main

Viewing History

Log & diffbash
# View commit log

git log –oneline –graph –all

# Show changes in working directory
git diff

# Show staged changes
git diff –staged

# Show a specific commit
git show a1b2c3d

# Who changed each line?
git blame src/Main.java
🧠
IntelliJ Tip: Press Alt+9 to open the Git log panel. It provides a visual commit graph, diff viewer, and branch filtering — much easier than the CLI for exploring history.
🌿

Branching

Branch Basics

Branches let you work on features, fixes, or experiments in isolation. They're lightweight pointers to commits — creating one is nearly instant.

Branch operationsbash
# List all branches (* = current)

git branch

# List remote branches
git branch -r

# Create a new branch
git branch feature/login-page

# Switch to a branch
git checkout feature/login-page

# Create AND switch (shorthand)
git checkout -b feature/login-page

# Modern alternative (Git 2.23+)
git switch -c feature/login-page

# Delete a local branch
git branch -d feature/login-page

# Force delete (unmerged branch)
git branch -D feature/login-page

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

Branch Naming Conventions

feature/*

New functionality
feature/user-auth
feature/JIRA-123-payment

bugfix/*

Bug fixes
bugfix/null-pointer-fix
bugfix/JIRA-456-login

hotfix/*

Urgent production fixes
hotfix/security-patch
hotfix/critical-crash

main
●───●───●───────────●───●
        ╲             ╱
         ●───●───●──● feature/login
🧠
IntelliJ Tip: Click the branch name in the bottom-right status bar to create, switch, or manage branches. You can also use Ctrl+Shift+` to open the VCS Operations popup.
🔀

Merging & Rebasing

🔀 Merge

  • Preserves full branch history
  • Creates a merge commit
  • Non-destructive operation
  • Best for shared/public branches
  • Safe for collaboration

📐 Rebase

  • ⚡ Creates a linear history
  • ⚡ No merge commits
  • ⚡ Rewrites commit history
  • ⚡ Best for local/private branches
  • ⚠️ Never rebase shared branches

Merge Commands

Merging a feature branch into mainbash
# Switch to the target branch

git checkout main

# Merge the feature branch
git merge feature/login-page

# Merge with no fast-forward (always create merge commit)
git merge –no-ff feature/login-page

# Abort a merge in progress
git merge –abort

Rebase Commands

Rebasing your feature onto mainbash
# Rebase current branch onto main

git checkout feature/login-page
git rebase main

# Interactive rebase (squash, reorder, edit commits)
git rebase -i HEAD~3

# Abort a rebase in progress
git rebase –abort

# Continue after resolving conflicts
git rebase –continue

Resolving Merge Conflicts

Conflicts happen when two branches modify the same lines. Git marks them in the file:

Conflict markerstext
<<<<<<< HEAD

# your changes on the current branch

incoming changes from the other branch
>>>>>>> feature/login-page
Resolve and continuebash
# After manually editing the file to resolve:
git add resolved-file.java
git commit
🚨
Golden Rule: Never rebase commits that have been pushed to a shared remote branch. Rewriting shared history causes chaos for your teammates.
🧠
IntelliJ Tip: IntelliJ has a powerful 3-way merge conflict resolver. When conflicts occur, go to Git → Resolve Conflicts to get a side-by-side view with yours, theirs, and the result.
🐙

GitHub Workflow

The GitHub Flow (Simplified)

GitHub Flow is a lightweight, branch-based workflow ideal for teams practicing continuous delivery.

GitHub Flow — Step by Step

1. Create Branch
2. Make Changes
3. Commit
4. Push
5. Open PR
6. Merge
1

Create a Branch

Branch off main with a descriptive name: git checkout -b feature/add-notifications

2

Make Changes & Commit

Write code, stage changes with git add, and commit with clear messages following conventional commits.

3

Push to Remote

Push your branch: git push origin feature/add-notifications

4

Open a Pull Request

On GitHub, open a PR against main. Add a description, link related issues, and request reviewers.

5

Code Review & CI

Teammates review your code. CI pipelines run automated tests. Address feedback with additional commits.

6

Merge & Deploy

Once approved, merge the PR (squash merge recommended for clean history). Delete the feature branch.

Remote Management

Working with remotesbash
# View remotes

git remote -v

# Add a remote
git remote add upstream https://github.com/original/repo.git

# Fetch all remote branches (without merging)
git fetch –all

# Pull = fetch + merge
git pull origin main

# Pull with rebase (cleaner history)
git pull –rebase origin main

# Push and set upstream tracking
git push -u origin feature/my-branch
Use git fetch regularly to stay aware of remote changes without modifying your working directory. It's always safe.
📝

Pull Requests

Anatomy of a Good PR

Title

Use conventional commit format:
feat: add email notification service
fix: resolve null pointer in UserDAO

Description

Explain what changed and why. Link JIRA tickets. Include screenshots for UI changes. List any breaking changes.

PR Merge Strategies

Merge Commit

Safe
Preserves all commits. Creates a merge commit. Full history retained.

Squash & Merge

Recommended
Combines all PR commits into one. Clean main branch history.

Rebase & Merge

Advanced
Replays commits on top of main. Linear history, no merge commit.

PR via CLI (GitHub CLI)

Using the gh CLI toolbash
# Create a PR

gh pr create –title “feat: add notifications” –body “Adds email notifications for overdue payments”

# List open PRs
gh pr list

# Check out a PR locally
gh pr checkout 42

# Merge a PR
gh pr merge 42 –squash
🧠
IntelliJ Tip: Use the GitHub plugin (bundled) to create and review PRs directly in the IDE. Go to Git → GitHub → Create Pull Request, or view PRs in the Pull Requests tool window.
🧠

IntelliJ IDEA Git Integration

Essential Keyboard Shortcuts

Action Shortcut Description
Commit Ctrl+K Open the commit dialog with diff preview
Push Ctrl+Shift+K Push commits to remote
Update Project Ctrl+T Pull/fetch latest changes
VCS Operations Ctrl+Shift+` Quick popup for common Git actions
Git Log Alt+9 Open the Git log tool window
Annotate (Blame) Right-click gutter Show who changed each line and when
Show Diff Ctrl+D Show diff for selected file in commit dialog
Rollback Changes Ctrl+Alt+Z Revert selected file to last committed state
Show History Right-click → Git → Show History View full commit history for a file
Resolve Conflicts Git → Resolve Conflicts Open the 3-way merge tool

IntelliJ Git Workflow

1

Create/Switch Branch

Click the branch indicator in the bottom-right corner, or use Ctrl+Shift+` → Branches.

2

Make Changes

Edit files normally. IntelliJ tracks changes automatically. Modified files appear in the Commit tool window (Alt+0).

3

Review & Commit

Press Ctrl+K. Review diffs inline, select files to include, write your commit message, and hit Commit.

4

Push

Press Ctrl+Shift+K to push. You can also "Commit and Push" in one step from the commit dialog.

Gutter Indicators

IntelliJ shows colored markers in the editor gutter:

  • 🟢 Green bar — New lines (added)
  • 🔵 Blue bar — Modified lines
  • ▶ Gray triangle — Deleted lines

Click any gutter marker to see the original code and quickly revert individual changes.

Changelists

IntelliJ lets you organize uncommitted changes into named changelists. Useful when working on multiple things at once:

  • 📋 Default Changelist — auto-assigned
  • 📋 Custom lists — drag files between them
  • 📋 Commit individual changelists separately

Shelve vs Stash in IntelliJ

📦 Shelve (IntelliJ-specific)

  • Stored in IntelliJ project settings
  • Can shelve individual changelists
  • Supports partial file shelving
  • Visible in Shelf tab of commit window

📦 Git Stash

  • Native Git feature (works in CLI too)
  • Stashes all uncommitted changes
  • Portable across tools
  • Access via Git → Unstash Changes
🧠
Pro Tip: Enable "Commit from the Git tool window" in Settings → Version Control → Commit for a more integrated commit experience with inline diff review.
📦

Stashing

Save Work in Progress

Stashing temporarily shelves your uncommitted changes so you can switch branches or pull updates without committing half-done work.

Stash operationsbash
# Stash all uncommitted changes

git stash

# Stash with a descriptive message
git stash push -m “WIP: halfway through login refactor”

# Stash including untracked files
git stash -u

# List all stashes
git stash list

# Apply most recent stash (keeps it in stash list)
git stash apply

# Apply and remove from stash list
git stash pop

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

# View stash contents
git stash show -p stash@{0}

# Drop a specific stash
git stash drop stash@{1}

# Clear all stashes
git stash clear
⚠️
Stashes are local only and not pushed to the remote. If you need to share work-in-progress, commit to a WIP branch instead.

Undoing Changes

Safety Levels

Git provides several ways to undo changes, ranging from safe to destructive:

🟢 Safe — Discard unstaged changes
Restore working directorybash
# Discard changes in a specific file

git checkout  file.java

# Modern alternative (Git 2.23+)
git restore file.java

# Discard ALL unstaged changes
git restore .
🟢 Safe — Unstage files
Remove from staging areabash
# Unstage a file (keep changes in working dir)

git reset HEAD file.java

# Modern alternative
git restore –staged file.java
🟡 Caution — Amend last commit
Fix the last commitbash
# Change the last commit message

git commit –amend -m “fix: corrected commit message”

# Add forgotten files to last commit
git add forgotten-file.java
git commit –amend –no-edit
⚠️
Only amend commits that haven’t been pushed yet. Amending rewrites history.
🟡 Caution — Revert a commit (safe undo)
Create a new commit that undoes a previous onebash
# Revert a specific commit (creates a new "undo" commit)

git revert a1b2c3d

# Revert without auto-committing
git revert –no-commit a1b2c3d

This is the safest way to undo a pushed commit — it doesn’t rewrite history.

🔴 Destructive — Reset commits
Reset to a previous statebash
# Soft reset: undo commit, keep changes staged

git reset –soft HEAD~1

# Mixed reset (default): undo commit, keep changes unstaged
git reset HEAD~1

# Hard reset: undo commit AND discard all changes
git reset –hard HEAD~1

# Reset to a specific commit
git reset –hard a1b2c3d
🚨
git reset –hard permanently destroys uncommitted changes. Use with extreme caution. If you’ve already pushed, use git revert instead.
🔴 Destructive — Clean untracked files
Remove untracked filesbash
# Preview what would be deleted

git clean -n

# Delete untracked files
git clean -f

# Delete untracked files AND directories
git clean -fd
🧠
IntelliJ Tip: Use Ctrl+Alt+Z to rollback changes on a file. IntelliJ also maintains a Local History (right-click → Local History → Show History) that works independently of Git — a lifesaver when you need to recover something Git can't.
🔄

Git Flow — Branching Strategy

Git Flow Overview

Git Flow is a structured branching model designed for projects with scheduled releases. It defines specific branch types and their roles.

main (production)
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━●━━━━━━━●
                             ╱      ╱
                        ●━━●       release/1.0
                       ╱          
develop
●━━━●━━━━━━━●━━━━━━━●━━━━━━━━━━━━━━━━━━●
     ╲      ╱     ╲    ╱
      ●━━●━●      ●━━●
      feature/A     feature/B

main

Production-ready code. Every commit here is a release. Tagged with version numbers.

develop

Integration branch for features. Always reflects the latest delivered development changes.

feature/*

Branch off develop, merge back into develop. One feature per branch.

release/*

Branch off develop when ready to release. Bug fixes only. Merges into both main and develop.

hotfix/*

Branch off main for urgent production fixes. Merges into both main and develop.

Tags

Tag every release on main: git tag -a v1.0.0 -m "Release 1.0.0"

Git Flow Commands

Common Git Flow operationsbash
# Start a new feature

git checkout develop
git checkout -b feature/user-profile

# Finish a feature (merge back to develop)
git checkout develop
git merge –no-ff feature/user-profile
git branch -d feature/user-profile

# Start a release
git checkout develop
git checkout -b release/1.2.0

# Finish a release
git checkout main
git merge –no-ff release/1.2.0
git tag -a v1.2.0 -m “Release 1.2.0”
git checkout develop
git merge –no-ff release/1.2.0

# Hotfix
git checkout main
git checkout -b hotfix/critical-fix
# … fix the issue …
git checkout main
git merge –no-ff hotfix/critical-fix
git tag -a v1.2.1
git checkout develop
git merge –no-ff hotfix/critical-fix
💡

Tips & Best Practices

Commit Message Conventions

Follow the Conventional Commits standard for clear, parseable history:

Formattext
type(scope): short description

Optional body with more detail.
Explain WHAT changed and WHY, not HOW.

Refs: JIRA-123

feat: New feature

fix: Bug fix

refactor: Code restructure

docs: Documentation

chore: Maintenance

test: Adding tests

✅ Do

  • Commit early and often
  • Write meaningful commit messages
  • Pull before you push
  • Use feature branches for all work
  • Review your diff before committing
  • Keep PRs small and focused
  • Use .gitignore properly
  • Tag releases on main

❌ Don't

  • Commit directly to main
  • Force push to shared branches
  • Commit secrets, passwords, or keys
  • Use vague messages like "fix stuff"
  • Rebase public/shared branches
  • Ignore merge conflicts
  • Commit build artifacts or node_modules
  • Let branches go stale for weeks

Essential .gitignore

Common entries for Java/IntelliJ projects.gitignore
# IntelliJ IDEA

.idea/
*.iml
*.iws
out/

# Build output
target/
build/
*.class
*.jar
*.war

# Environment & secrets
.env
*.properties.local
application-local.yml

# OS files
.DS_Store
Thumbs.db

# Logs
*.log
logs/

Useful Git Aliases

Add to your ~/.gitconfigbash
git config --global alias.st "status -sb"

git config –global alias.co “checkout”
git config –global alias.br “branch”
git config –global alias.ci “commit”
git config –global alias.lg “log –oneline –graph –all –decorate”
git config –global alias.last “log -1 HEAD –stat”
git config –global alias.unstage “restore –staged”

Quick Reference Cheat Sheet

Task Command Safety
See what changed git status Safe
Stage everything git add . Safe
Commit changes git commit -m "msg" Safe
Push to remote git push origin branch Safe
Pull latest git pull origin main Safe
Create branch git checkout -b name Safe
Stash changes git stash Safe
Undo last commit (keep changes) git reset --soft HEAD~1 Caution
Revert a pushed commit git revert <sha> Safe
Nuke everything git reset --hard HEAD~1 Destructive
When in doubt, git reflog is your safety net. It records every HEAD movement, so you can recover from almost any mistake within 30 days.