Git and GitHub: The Complete Beginner-to-Advanced Guide

Git and GitHub: The Complete Beginner-to-Advanced Guide

Git and GitHub are essential tools for modern software development. Whether you are building a personal project, contributing to open-source software, or working with a development team, understanding them helps you manage code, collaborate efficiently, and maintain a reliable development history.

In this comprehensive guide, we will learn Git and GitHub from the fundamentals to advanced workflows, including the commands developers use in real-world projects.

By the end, you will understand how to initialize repositories, manage commits, work with branches, resolve conflicts, collaborate through pull requests, recover lost work, and automate development workflows.

Table of Contents

  1. What is version control?
  2. Git vs. GitHub
  3. Installing and configuring Git
  4. Understanding Git's architecture
  5. Creating and cloning repositories
  6. Essential Git commands
  7. Working with commits
  8. Branching and merging
  9. Working with remote repositories
  10. GitHub collaboration and pull requests
  11. Undoing and recovering changes
  12. Stashing and cherry-picking
  13. Rebasing and interactive rebase
  14. Tags and releases
  15. Git internals
  16. Advanced Git commands
  17. GitHub CLI and GitHub Actions
  18. Professional Git workflows
  19. Troubleshooting common errors
  20. Git best practices
  21. Complete command cheat sheet
  22. Practice projects and conclusion

1. What Is Version Control?

Version control is a system that records changes made to files over time.

Imagine building a web application. You make changes to your homepage, add authentication, update your database schema, and introduce a new feature.

Without version control, you might create files such as:

project/
├── app-final/
├── app-final-new/
├── app-final-working/
├── app-final-really-final/
└── app-final-final-v2/

This quickly becomes confusing.

A version control system allows you to maintain a history of changes without creating multiple copies of your project.

Benefits of version control

  • Track every meaningful change to your code.
  • Restore previous versions when something breaks.
  • Work on multiple features independently.
  • Collaborate with other developers.
  • Review code before merging it.
  • Maintain a record of who changed what and why.

Types of version control systems

| Type | Description | | --------------- | ------------------------------------------------------- | | Local VCS | Stores versions on one computer. | | Centralized VCS | Uses a central server to store version history. | | Distributed VCS | Each clone can contain the complete repository history. |

Git is a distributed version control system.


2. Git vs. GitHub

Git and GitHub are related, but they are not the same thing.

What is Git?

Git is a version control tool that runs on your computer.

It allows you to:

  • Track changes.
  • Create commits.
  • Manage branches.
  • Compare versions.
  • Merge changes.
  • Recover previous work.

What is GitHub?

GitHub is a cloud-based platform for hosting Git repositories and collaborating with other developers.

It provides features such as:

  • Remote repository hosting.
  • Pull requests and code reviews.
  • Issues and project management.
  • GitHub Actions for automation.
  • Repository permissions and security settings.
  • Releases and project documentation.

Comparison

| Git | GitHub | | ---------------------------------- | --------------------------------------------- | | Version control software | Repository hosting and collaboration platform | | Works locally | Accessed through the web, APIs, and CLI | | Uses commands such as git commit | Provides pull requests, issues, and Actions | | Does not require GitHub | Commonly used with Git |

Remember: Git manages the history of your code. GitHub helps you share that history and collaborate with others.


3. Installing Git

macOS

If you use Homebrew:

brew install git

Alternatively, install Apple's command-line developer tools:

xcode-select --install

Ubuntu and Debian

sudo apt update
sudo apt install git

Windows

Download Git from:

https://git-scm.com/downloads

You can use Git Bash, PowerShell, or Windows Terminal.

Verify installation

git --version

Example output:

git version 2.x.x

The exact version depends on your installation.

Open Git help

git help

Show help for a particular command:

git help commit

Or:

git commit --help

For a quick overview:

git commit -h

4. Configure Git

Before creating commits, configure your name and email address.

Set your global username

git config --global user.name "Urvil Patel"

Set your global email

git config --global user.email "your-email@example.com"

Use an email address associated with your GitHub account if you want GitHub to associate your commits with your profile.

View configuration

git config --list

Show a specific value:

git config user.name
git config user.email

Set the default branch name

git config --global init.defaultBranch main

This configures newly initialized repositories to use main as their initial branch name.

Set the default editor

For Visual Studio Code:

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

For Vim:

git config --global core.editor "vim"

Understand Git configuration levels

Git supports three main configuration scopes:

| Scope | Meaning | | ---------- | ------------------------------------------- | | --system | Applies to all users on the system. | | --global | Applies to the current user's repositories. | | --local | Applies only to the current repository. |

Example:

git config --local user.name "Project Contributor"

Local configuration overrides global configuration for the same setting.


5. Understanding Git's Architecture

Before learning commands, understand how Git stores changes.

Git uses three main areas in the everyday development workflow.

Working Directory | | git add v Staging Area | | git commit v Local Repository | | git push v Remote Repository (GitHub)

Working directory

The working directory contains the files you are currently editing.

For example:

my-project/
├── app/
├── components/
├── package.json
└── README.md

Staging area

The staging area contains changes selected for the next commit.

You can stage one file, multiple files, or specific parts of a file.

Local repository

The local repository contains commits and Git's recorded history.

Remote repository

A remote repository is another copy of the repository, commonly hosted on GitHub.

It allows you to share changes and synchronize work with collaborators.

The basic Git workflow

git add .
git commit -m "Add homepage"
git push

This stages changes, records a commit locally, and pushes the commit to a remote repository.


6. Creating Your First Git Repository

Let's create a simple project.

Step 1: Create a project directory

mkdir git-practice
cd git-practice

Step 2: Initialize Git

git init

This creates a new Git repository in the current directory.

Step 3: Create a file

echo "# Git Practice" > README.md

Step 4: Check repository status

git status

You should see that README.md is an untracked file.

Step 5: Stage the file

git add README.md

Step 6: Create a commit

git commit -m "Initial commit"

Your first commit is now recorded.

Step 7: Inspect commit history

git log

Congratulations! You have created your first Git repository and committed a file.


7. Essential Git Commands

This section covers the commands you will use regularly.

7.1 git status

Displays the current state of your repository.

git status

It helps you understand:

  • Which files have changed.
  • Which files are staged.
  • Which files are untracked.
  • Whether your branch is ahead of or behind its upstream branch.

Short format:

git status -s

Example:

 M README.md
?? app.js

Here, M indicates a modified tracked file, and ?? indicates an untracked file.

7.2 git add

Adds file changes to the staging area.

Stage a particular file:

git add README.md

Stage multiple files:

git add README.md app.js

Stage all changes in the current directory:

git add .

Stage all changes throughout the working tree, including deletions:

git add -A

Stage only modifications and deletions of tracked files:

git add -u

Interactively select changes:

git add -p

The interactive option is particularly useful when a file contains changes that belong in different commits.

7.3 git commit

Records the staged changes as a new commit.

git commit -m "Add user authentication"

Write a longer commit message:

git commit

Git opens your configured editor.

Commit all modified tracked files without explicitly staging them:

git commit -am "Update homepage"

Important: -a does not include new untracked files.

7.4 git log

Displays commit history.

git log

Compact history:

git log --oneline

Show branches and merge history:

git log --oneline --graph --decorate --all

Show the last five commits:

git log -5

Show commits by an author:

git log --author="Urvil Patel"

Show commits affecting a particular file:

git log -- app.js

7.5 git diff

Displays differences between versions of files.

Show unstaged changes:

git diff

Show staged changes:

git diff --staged

Compare two commits:

git diff abc123 def456

Compare two branches:

git diff main..feature/login

Show only changed file names:

git diff --name-only

Show a summary of changed files:

git diff --stat

7.6 git show

Displays information about a commit or Git object.

git show

Show a specific commit:

git show abc123

Show the contents of a file from a previous commit:

git show abc123:README.md

7.7 git rm

Removes a tracked file and stages its deletion.

git rm old-file.js

Remove a file from Git tracking but keep it on your computer:

git rm --cached .env

Remove a directory recursively:

git rm -r old-folder

7.8 git mv

Renames or moves a tracked file.

git mv old-name.js new-name.js

Git records the resulting changes, and commit detection identifies renames based on file similarity.


8. Working with .gitignore

A .gitignore file tells Git which untracked files and directories to ignore.

This is particularly important in Next.js, Node.js, Python, and machine learning projects.

Example .gitignore:

# Dependencies
node_modules/

# Build output
.next/
dist/
build/

# Environment variables
.env
.env.local
.env.production

# Python
__pycache__/
.venv/
*.pyc

# Logs
*.log

# Editor files
.vscode/
.DS_Store

Ignore a specific file

secret.txt

Ignore all files with an extension

*.log

Ignore a directory

uploads/

Ignore everything inside a directory except one file

logs/*
!logs/README.md

Check whether a file is ignored

git check-ignore -v .env

This shows which ignore rule matches the file.

Important: .gitignore does not untrack existing files

If a file is already tracked, adding it to .gitignore does not remove it from Git history.

To stop tracking it while keeping the local file:

git rm --cached .env
git commit -m "Stop tracking environment file"

If the file contains a real secret, removing it from the latest commit is not sufficient to erase it from previous commits. Revoke or rotate the exposed credential immediately.


9. Branching in Git

A branch is a movable reference to a commit.

Branches allow you to develop features independently without immediately changing the main branch.

For example:

main
 |
 A --- B --- C
              \
               D --- E   feature/login

Here, the feature branch contains additional commits while main remains unchanged.

9.1 List branches

git branch

List all local and remote-tracking branches:

git branch -a

9.2 Create a branch

git branch feature/login

9.3 Switch branches

git switch feature/login

9.4 Create and switch in one command

git switch -c feature/signup

9.5 Rename a branch

Rename the current branch:

git branch -m feature/auth

Rename a different local branch:

git branch -m old-name new-name

9.6 Delete a branch

Delete a merged local branch:

git branch -d feature/login

Force-delete a local branch:

git branch -D feature/login

Use -D carefully because it can remove a branch reference containing work that has not been merged.

9.7 Show the current branch

git branch --show-current

9.8 Switch to a remote branch

git switch --track origin/feature/login

This creates a local branch that tracks the remote branch.


10. Merging Branches

Merging combines changes from one branch into another.

Suppose you have completed a login feature and want to merge it into main.

git switch main
git merge feature/login

The merge operation integrates the feature branch into the current branch.

Fast-forward merge

If main has not changed since the feature branch was created, Git may simply move the main reference forward.

git merge --ff-only feature/login

This permits the merge only if it can be completed as a fast-forward.

Create a merge commit

git merge --no-ff feature/login

This creates a merge commit even when a fast-forward would be possible.

Abort a merge

If a merge is in progress and you want to cancel it:

git merge --abort

Use this when you want to return to the pre-merge state, provided Git can safely restore it.


11. Resolving Merge Conflicts

A merge conflict occurs when Git cannot automatically combine changes.

For example, two developers modify the same line of a file.

Git may produce:

<<<<<<< HEAD
const title = "Dashboard";
=======
const title = "Admin Dashboard";
>>>>>>> feature/admin

Understanding conflict markers

| Marker | Meaning | | ----------------------- | ---------------------------------------- | | <<<<<<< HEAD | Starts the current side of the conflict. | | ======= | Separates the two versions. | | >>>>>>> feature/admin | Ends the incoming side. |

Steps to resolve a conflict

  1. Open the conflicted file.
  2. Decide which changes to keep.
  3. Edit the file and remove the conflict markers.
  4. Test the resulting code.
  5. Stage the resolved file.
  6. Complete the merge.
git add app.js
git commit

If the merge was initiated through a pull request on GitHub, resolve the conflict locally or through GitHub's available conflict-resolution interface.

Best practice: Understand both versions before resolving a conflict. Do not blindly choose one side.


12. Working with Remote Repositories

A remote is a named reference to another repository.

GitHub repositories are commonly configured as remotes.

12.1 View remotes

git remote

Show remote URLs:

git remote -v

12.2 Add a remote

git remote add origin https://github.com/USERNAME/REPOSITORY.git

origin is a conventional name for the primary remote, but you can choose another name.

12.3 Change a remote URL

git remote set-url origin https://github.com/USERNAME/NEW-REPOSITORY.git

12.4 Remove a remote

git remote remove origin

12.5 Rename a remote

git remote rename origin upstream

12.6 Clone a repository

git clone https://github.com/USERNAME/REPOSITORY.git

Clone into a custom directory:

git clone https://github.com/USERNAME/REPOSITORY.git my-project

Clone a particular branch:

git clone --branch main https://github.com/USERNAME/REPOSITORY.git

Clone without downloading the full history:

git clone --depth 1 https://github.com/USERNAME/REPOSITORY.git

This creates a shallow clone.

12.7 Push changes

git push origin main

Push the current branch and configure its upstream:

git push -u origin feature/login

After setting the upstream, you can usually use:

git push

12.8 Fetch changes

git fetch origin

Fetch all remotes:

git fetch --all

Fetch and prune deleted remote-tracking branches:

git fetch --prune

Fetching downloads remote information but does not automatically merge it into your current branch.

12.9 Pull changes

git pull

Pull changes from a specific remote and branch:

git pull origin main

Pull using rebase:

git pull --rebase

A pull generally fetches changes and integrates them into the current branch. Depending on configuration and options, that integration can use a merge or a rebase.

12.10 Compare local and remote branches

git log HEAD..origin/main --oneline

Shows commits reachable from origin/main that are not reachable from the current HEAD.

git log origin/main..HEAD --oneline

Shows commits reachable from the current HEAD that are not reachable from origin/main.


13. Connecting Git to GitHub

Let's publish a local project to GitHub.

Step 1: Create a GitHub repository

On GitHub:

  1. Sign in to your account.
  2. Create a new repository.
  3. Choose a repository name.
  4. Choose public or private visibility.
  5. Create the repository.

If you already have a local project, you can leave the remote repository empty to avoid unnecessary initial-history conflicts.

Step 2: Initialize Git locally

git init
git add .
git commit -m "Initial commit"

Step 3: Configure the remote

git remote add origin https://github.com/USERNAME/REPOSITORY.git

Step 4: Set the branch name

git branch -M main

Step 5: Push to GitHub

git push -u origin main

Your repository is now available on GitHub.

Authentication

GitHub supports authentication through HTTPS or SSH.

For HTTPS, use GitHub's supported authentication methods, such as Git Credential Manager or a personal access token when required.

For SSH, create and register an SSH key with your GitHub account.

Do not put access tokens or private SSH keys inside source code or repository files.


14. GitHub Collaboration and Pull Requests

A pull request (PR) is a request to merge changes from one branch into another.

It allows developers to review code, discuss implementation details, and run automated checks before merging.

Typical collaboration workflow

Clone repository
      |
      v
Create feature branch
      |
      v
Make changes
      |
      v
Commit and push
      |
      v
Open pull request
      |
      v
Review and test
      |
      v
Merge into main

Step 1: Clone the repository

git clone https://github.com/USERNAME/REPOSITORY.git
cd REPOSITORY

Step 2: Create a feature branch

git switch -c feature/profile-page

Step 3: Make changes and commit

git add .
git commit -m "Add user profile page"

Step 4: Push the branch

git push -u origin feature/profile-page

Step 5: Open a pull request

On GitHub, open a pull request from feature/profile-page into main.

Include:

  • A clear title.
  • A description of the changes.
  • Screenshots for UI changes, where useful.
  • Testing instructions.
  • Related issue references.

Step 6: Review and merge

After the required reviews and checks pass, merge the pull request using the repository's configured merge method.

Delete a remote branch

git push origin --delete feature/profile-page

Many teams automatically delete feature branches after merging.

Protect the main branch

Repository maintainers can configure branch protection or repository rulesets to require pull requests, approvals, successful status checks, and other safeguards.

This helps prevent accidental changes to important branches.


15. Forking and Contributing to Open Source

A fork is a GitHub-hosted copy of a repository under a different account or organization.

Forking is a common workflow for contributing to projects where you do not have direct write access.

Step 1: Fork the repository

Use the Fork button on the original GitHub repository.

Step 2: Clone your fork

git clone https://github.com/YOUR_USERNAME/PROJECT.git
cd PROJECT

Step 3: Add the original repository as upstream

git remote add upstream https://github.com/ORIGINAL_OWNER/PROJECT.git

Step 4: Verify remotes

git remote -v

You should see origin pointing to your fork and upstream pointing to the original repository.

Step 5: Create a feature branch

git switch -c fix/documentation

Step 6: Make changes and push

git add .
git commit -m "Fix installation documentation"
git push -u origin fix/documentation

Step 7: Open a pull request

Create a pull request from your fork's feature branch into the original repository's target branch.

Synchronize your fork

Fetch the original repository:

git fetch upstream

Update your local main:

git switch main
git merge upstream/main

Update your fork on GitHub:

git push origin main

You can also use a rebase workflow if that matches the project's contribution guidelines.


16. Undoing Changes in Git

Git provides several commands for undoing changes. Choosing the right command is important because some operations can discard work or rewrite history.

16.1 git restore

Discard unstaged changes to a tracked file:

git restore app.js

Restore multiple files:

git restore app.js README.md

Unstage a file while keeping its working-directory changes:

git restore --staged app.js

Restore a file from a specific commit:

git restore --source=abc123 README.md

Restore both the index and working tree from a commit:

git restore --source=abc123 --staged --worktree README.md

Warning: Restoring a file can overwrite local changes. Check your status and diff first.

16.2 git reset

Moves the current branch reference to another commit, with different effects depending on the selected mode.

Soft reset

git reset --soft HEAD~1

Removes the latest commit from the current branch while keeping its changes staged.

Mixed reset

git reset --mixed HEAD~1

Removes the latest commit while keeping its changes in the working directory, unstaged.

--mixed is the default mode.

git reset HEAD~1

Hard reset

git reset --hard HEAD~1

Moves the branch backward and resets the index and working tree.

Warning: This can permanently discard tracked changes that are not recoverable through another reference or recovery mechanism.

16.3 git revert

Creates a new commit that reverses the changes introduced by an earlier commit.

git revert abc123

Revert the latest commit:

git revert HEAD

This is generally safer than rewriting shared history because it preserves existing commits.

Reset vs. Revert

| Command | What it does | Best use | | ------------- | -------------------------------------------- | ------------------------------------ | | git reset | Moves a branch reference and may reset files | Local history cleanup | | git revert | Creates a new commit that reverses changes | Undoing changes in shared history | | git restore | Restores file contents or the staging state | Discarding or unstaging file changes |


17. Stashing Changes

Git stash temporarily stores changes so you can switch tasks without committing incomplete work.

Save current changes

git stash

Save changes with a message:

git stash push -m "Work in progress: dashboard"

Include untracked files:

git stash -u

Include ignored files as well:

git stash -a

Use the latter carefully because ignored files can contain dependencies, build output, or secrets.

List stashes

git stash list

Apply the latest stash

git stash apply

Apply a particular stash:

git stash apply stash@{1}

Apply and remove the stash

git stash pop

Delete a stash

git stash drop stash@{0}

Delete all stashes:

git stash clear

Important: git stash clear removes all stash references. Avoid using it unless you are sure you no longer need them.


18. Cherry-Picking Commits

Cherry-picking applies the changes introduced by selected commits onto your current branch.

Imagine you have a bug fix on another branch and want to apply it to your current branch without merging the entire branch.

git switch main
git cherry-pick abc123

Cherry-pick multiple commits:

git cherry-pick abc123 def456

Cherry-pick a range of commits:

git cherry-pick abc123..def456

This range excludes abc123 and includes commits reachable through def456 that are in the specified range.

Cherry-pick without automatically committing:

git cherry-pick --no-commit abc123

Abort an in-progress cherry-pick:

git cherry-pick --abort

Continue after resolving conflicts:

git add .
git cherry-pick --continue

Cherry-picking creates new commits with the selected changes, so the resulting commit IDs differ from the original commits.


19. Rebasing

Rebasing moves or replays commits onto another base commit.

It is often used to update a feature branch with the latest changes from main.

Suppose the history looks like this:

A --- B --- C  main
       \
        D --- E  feature

After rebasing the feature branch onto main:

A --- B --- C  main
             \
              D' --- E'  feature

The feature commits are replayed on top of main, producing new commit IDs.

Rebase onto main

git switch feature
git fetch origin
git rebase origin/main

Rebase interactively

git rebase -i HEAD~3

This opens an editor where you can choose how to handle the selected commits.

Common interactive rebase actions:

| Action | Meaning | | -------- | ------------------------------------------------------------------ | | pick | Keep the commit. | | reword | Change the commit message. | | edit | Stop to amend a commit. | | squash | Combine a commit with the previous commit and edit the messages. | | fixup | Combine a commit with the previous commit, discarding its message. | | drop | Remove the commit from the rebased history. |

Abort a rebase

git rebase --abort

Continue after resolving conflicts

git add .
git rebase --continue

Skip the current commit

git rebase --skip

Use --skip only when you intentionally want to omit the changes from the current commit.

Important rebase rule

Avoid rebasing commits that other developers are already using unless your team has explicitly coordinated the history rewrite.

If you need to update a feature branch that you have already pushed, you may need:

git push --force-with-lease

This is safer than a plain force push, but it still rewrites remote history. Use it only on a branch where rewriting history is acceptable.


20. Tags and Releases

Tags identify specific commits, often to mark releases.

List tags

git tag

Create a lightweight tag

git tag v1.0.0

Create an annotated tag

git tag -a v1.0.0 -m "Release version 1.0.0"

Annotated tags contain metadata such as the tagger, date, and message.

Show a tag

git show v1.0.0

Push a tag

git push origin v1.0.0

Push all local tags:

git push origin --tags

Delete a local tag

git tag -d v1.0.0

Delete a remote tag

git push origin --delete v1.0.0

Create a GitHub release

A typical release workflow is:

  1. Create and push a release tag.
  2. Open the repository's Releases page.
  3. Create a release based on the tag.
  4. Add release notes and any required assets.
  5. Publish the release.

Semantic versioning commonly uses:

MAJOR.MINOR.PATCH

For example:

1.0.0
  • MAJOR: incompatible changes.
  • MINOR: backward-compatible features.
  • PATCH: backward-compatible fixes.

21. Advanced Git Commands

21.1 git reflog

The reflog records changes to local references, including movements of HEAD.

It is useful when you accidentally reset a branch or lose track of a recent commit.

git reflog

Example:

abc123 HEAD@{0}: reset: moving to HEAD~1
def456 HEAD@{1}: commit: Add profile page

You may be able to recover the previous commit:

git reset --hard def456

Use a recovery reference only after verifying it is the commit you want.

Reflogs are local and expire according to Git's retention settings. They are not a substitute for backups.

21.2 git bisect

Use binary search to find which commit introduced a bug.

Start a bisect session:

git bisect start

Mark the current commit as bad:

git bisect bad

Mark a known-good commit:

git bisect good abc123

Git checks out commits for you to test.

After each test, mark the current commit:

git bisect good

Or:

git bisect bad

When the faulty commit is identified:

git bisect reset

21.3 git blame

Shows the last commit that modified each line of a file.

git blame app.js

Show line history for a specific range:

git blame -L 10,30 app.js

This helps you investigate when and why a particular line was introduced.

21.4 git clean

Removes untracked files.

Preview which files would be removed:

git clean -n

Preview untracked files and directories:

git clean -nd

Remove untracked files:

git clean -f

Remove untracked files and directories:

git clean -fd

Warning: git clean can permanently delete untracked work. Always preview the result before using it.

21.5 git worktree

Allows you to check out multiple branches into separate working directories linked to one repository.

Create a worktree for another branch:

git worktree add ../hotfix hotfix/login

Create a new branch and worktree:

git worktree add -b feature/search ../search main

List worktrees:

git worktree list

Remove a worktree:

git worktree remove ../hotfix

This is useful when you need to work on a hotfix without disturbing your current development environment.

21.6 git archive

Creates an archive of a repository tree.

git archive --format=zip --output=source.zip HEAD

This creates a ZIP archive of the files represented by HEAD, without the Git repository history.

21.7 git bundle

Creates a file containing Git objects and references that can be transferred without a normal remote connection.

git bundle create project.bundle --all

Clone from a bundle:

git clone project.bundle project-copy

Bundles can be useful for offline transfers and repository backups.

21.8 git shortlog

Summarizes commits by author.

git shortlog

Show a concise author summary:

git shortlog -sn

This can help review contributions over a particular range.


22. Git Internals

Understanding Git internals helps explain why Git is reliable and how advanced commands work.

Git stores content using objects.

Blob

A blob stores file contents.

It does not store the file name or directory structure.

Tree

A tree represents a directory structure. It points to blobs and other trees.

Commit

A commit records a snapshot reference, parent commit information, author information, committer information, and a commit message.

Tag

An annotated tag is an object that points to another Git object, commonly a commit.

Inspect Git objects

Find an object's type:

git cat-file -t abc123

Display object contents:

git cat-file -p abc123

Show the repository's object database:

git count-objects -v

What is HEAD?

HEAD identifies the current checkout, usually through the current branch reference.

For example:

git show HEAD

The notation:

HEAD~1

means the first parent of the current commit.

HEAD~3

means three first-parent steps back.

The notation:

HEAD^

means the first parent.

For a merge commit:

HEAD^2

refers to the second parent.

Commit hashes

Git identifies objects using hash-based object IDs.

Modern Git repositories can use SHA-1 or SHA-256 object formats, depending on how the repository was initialized.

Do not assume that every repository uses a particular hash length.


23. GitHub CLI

GitHub CLI, commonly called gh, allows you to interact with GitHub from your terminal.

Install it using the instructions on:

https://cli.github.com/

Authenticate

gh auth login

Check authentication status:

gh auth status

Create a GitHub repository

gh repo create my-project --public

Create a private repository:

gh repo create my-project --private

Clone a repository

gh repo clone OWNER/REPOSITORY

View pull requests

gh pr list

Create a pull request

gh pr create

Create a pull request with a title and body:

gh pr create --title "Add profile page" --body "Implements the user profile page."

Check out a pull request locally

gh pr checkout 42

Review a pull request

gh pr review 42

Merge a pull request

gh pr merge 42

View repository information

gh repo view

The GitHub CLI supports many more commands for issues, releases, workflows, and repository management.


24. GitHub Actions: Automating Your Workflow

GitHub Actions is a platform for automating software development workflows.

You can use it to run tests, check code quality, build applications, and deploy projects.

Workflows are defined using YAML files inside:

.github/workflows/

Example: Run tests on every push and pull request

Create .github/workflows/ci.yml:

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

This is an illustrative workflow. Adjust the Node.js version, action versions, package manager, and test command to match your project.

Important concepts

| Concept | Meaning | | -------- | -------------------------------------- | | Workflow | An automated process defined in YAML. | | Event | An action that triggers a workflow. | | Job | A group of steps that run on a runner. | | Step | An individual action or shell command. | | Runner | The environment that executes a job. | | Action | A reusable unit of automation. |

GitHub Actions best practices

  • Pin third-party actions to trusted versions or immutable commit SHAs according to your security requirements.
  • Do not expose secrets in logs.
  • Give workflows only the permissions they need.
  • Use protected branches and required status checks.
  • Test workflow changes before relying on them for deployment.

25. Git Workflows Used in Professional Teams

Feature branch workflow

This is one of the most common workflows for application development.

git switch main
git pull --ff-only origin main

git switch -c feature/user-profile

# Make changes

git add .
git commit -m "Add user profile"

git push -u origin feature/user-profile

Then open a pull request, receive reviews, and merge.

Hotfix workflow

For an urgent production bug:

git switch main
git pull --ff-only origin main

git switch -c hotfix/login-error

# Fix the bug

git add .
git commit -m "Fix login error"

git push -u origin hotfix/login-error

Open a pull request and follow your team's release process.

Conventional Commits

Conventional Commits is a popular commit-message convention.

Examples:

feat: add user authentication
fix: resolve login validation bug
docs: update installation guide
refactor: simplify API service
test: add authentication tests
chore: update dependencies

A commit message may also include a scope:

feat(auth): add Google login

This convention can make project history easier to read and support automated changelog generation.

Commit message best practices

A good commit message explains the purpose of the change.

Prefer:

git commit -m "Fix password reset validation"

Avoid:

git commit -m "changes"

Each commit should ideally represent one logical change.


26. Common Git Errors and Their Solutions

Error: fatal: not a git repository

You are not currently inside a Git repository.

Check your location:

pwd

Move into your project directory:

cd my-project

If the directory is not yet a repository:

git init

Error: Author identity unknown

Configure your Git identity:

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

Error: remote origin already exists

Check existing remotes:

git remote -v

Update the existing URL:

git remote set-url origin https://github.com/USERNAME/REPOSITORY.git

Error: rejected because the remote contains work

The remote branch contains commits your local branch does not have.

Inspect the remote history:

git fetch origin
git log --oneline --graph --all

If the histories are related, integrate the remote changes:

git pull --rebase origin main

Resolve any conflicts and then push.

Do not immediately force-push over remote history.

Error: CONFLICT

Git cannot automatically combine the changes.

Check conflicted files:

git status

Resolve the conflicts, stage the files, and continue the merge or rebase.

Error: Permission denied (publickey)

Your SSH authentication may not be configured correctly.

Check the SSH connection:

ssh -T git@github.com

Verify that your public SSH key is registered with GitHub and that your SSH agent is configured.

Error: Accidentally committed the wrong file

If the commit is local and you have not shared it, you may be able to correct it with:

git rm --cached unwanted-file
git commit --amend

If the commit has already been shared, coordinate with your team and prefer a corrective commit when appropriate.

Error: Accidentally committed a secret

Immediately revoke or rotate the exposed credential.

Then remove it from the current code and prevent it from being committed again.

If the secret exists in Git history, history rewriting may be necessary. Coordinate with collaborators because rewriting history affects everyone using the repository.


27. Git Best Practices

Keep commits small

Small commits are easier to review, understand, test, and revert.

Use descriptive branch names

Examples:

feature/user-auth
fix/navbar-responsive
hotfix/payment-error
docs/api-guide

Pull or fetch before starting new work

Start from an up-to-date branch to reduce unnecessary conflicts.

Never commit secrets

Keep API keys, database credentials, access tokens, and private keys out of your repository.

Use pull requests

Pull requests provide a structured way to review and discuss changes before merging.

Protect important branches

Configure rules that require reviews and successful automated checks before merging.

Avoid unnecessary force pushes

A force push can remove commits that other collaborators depend on.

Use --force-with-lease only when rewriting history is appropriate.

Keep .gitignore updated

Exclude dependencies, build artifacts, temporary files, and sensitive local configuration.

Write useful README files

A good README should explain:

  • What the project does.
  • How to install it.
  • How to configure it.
  • How to run it.
  • How to test it.
  • How to contribute.

Practice recovery commands

Understand git restore, git reset, git revert, and git reflog before using them on important projects.


28. Complete Git Command Cheat Sheet

Setup and configuration

git --version
git config --list
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git help

Repository management

git init
git clone URL
git status
git remote -v
git remote add origin URL

Staging and commits

git add .
git add -p
git commit -m "message"
git commit -am "message"
git commit --amend
git diff
git diff --staged
git show
git log --oneline --graph --all

Branching and merging

git branch
git branch -a
git switch main
git switch -c feature/new
git branch -d feature/new
git merge feature/new
git merge --abort

Remote operations

git fetch origin
git fetch --all
git pull
git pull --rebase
git push
git push -u origin feature/new
git push origin --delete feature/new

Undoing and recovering

git restore file.js
git restore --staged file.js
git reset --soft HEAD~1
git reset --mixed HEAD~1
git reset --hard HEAD~1
git revert HEAD
git reflog

Advanced operations

git stash
git stash list
git stash pop
git cherry-pick abc123
git rebase main
git rebase -i HEAD~3
git bisect start
git blame file.js
git clean -n
git worktree list

Tags and releases

git tag
git tag -a v1.0.0 -m "Release 1.0.0"
git push origin v1.0.0
git push origin --tags

29. Practice Projects

The best way to learn Git is by using it in real projects.

Beginner: Personal portfolio

Create a portfolio project and practice:

  • git init
  • git add
  • git commit
  • git status
  • git log
  • git push

Intermediate: Feature branch workflow

Build a simple task management application.

Create branches for:

  • User authentication.
  • Task creation.
  • Task editing.
  • Dashboard UI.

Practice merging each feature through a pull request.

Advanced: Open-source contribution

Choose an open-source repository.

Practice:

  • Forking.
  • Cloning.
  • Adding an upstream remote.
  • Creating a feature branch.
  • Resolving conflicts.
  • Rebasing your feature branch.
  • Opening a pull request.

Expert: Simulate a production incident

Create a small application and intentionally introduce a bug.

Practice:

  • Finding the faulty commit with git bisect.
  • Inspecting file history with git blame.
  • Recovering a commit with git reflog.
  • Reverting a faulty change.
  • Creating a hotfix branch.

30. Conclusion

Git and GitHub are much more than tools for uploading code. They form the foundation of modern software development collaboration.

Start by mastering the essential commands:

git status
git add
git commit
git log
git diff
git branch
git switch
git merge
git fetch
git pull
git push

Then progress to advanced concepts such as rebasing, cherry-picking, stashing, reflog recovery, Git internals, GitHub CLI, and automated workflows.

The most important skill is not memorizing every command. It is understanding how Git tracks changes, how branches relate to one another, and how to safely recover from mistakes.

Practice these workflows in your own projects, contribute to open-source repositories, and use Git consistently in your development process.

With regular practice, Git and GitHub will become natural parts of your everyday software engineering workflow.


Official Resources

Build with love by Urvil Patel