
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.
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.
| 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.
Git and GitHub are related, but they are not the same thing.
Git is a version control tool that runs on your computer.
It allows you to:
GitHub is a cloud-based platform for hosting Git repositories and collaborating with other developers.
It provides features such as:
| 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.
If you use Homebrew:
brew install git
Alternatively, install Apple's command-line developer tools:
xcode-select --install
sudo apt update
sudo apt install git
Download Git from:
https://git-scm.com/downloads
You can use Git Bash, PowerShell, or Windows Terminal.
git --version
Example output:
git version 2.x.x
The exact version depends on your installation.
git help
Show help for a particular command:
git help commit
Or:
git commit --help
For a quick overview:
git commit -h
Before creating commits, configure your name and email address.
git config --global user.name "Urvil Patel"
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.
git config --list
Show a specific value:
git config user.name
git config user.email
git config --global init.defaultBranch main
This configures newly initialized repositories to use main as their initial branch name.
For Visual Studio Code:
git config --global core.editor "code --wait"
For Vim:
git config --global core.editor "vim"
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.
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)
The working directory contains the files you are currently editing.
For example:
my-project/
├── app/
├── components/
├── package.json
└── README.md
The staging area contains changes selected for the next commit.
You can stage one file, multiple files, or specific parts of a file.
The local repository contains commits and Git's recorded history.
A remote repository is another copy of the repository, commonly hosted on GitHub.
It allows you to share changes and synchronize work with collaborators.
git add .
git commit -m "Add homepage"
git push
This stages changes, records a commit locally, and pushes the commit to a remote repository.
Let's create a simple project.
mkdir git-practice
cd git-practice
git init
This creates a new Git repository in the current directory.
echo "# Git Practice" > README.md
git status
You should see that README.md is an untracked file.
git add README.md
git commit -m "Initial commit"
Your first commit is now recorded.
git log
Congratulations! You have created your first Git repository and committed a file.
This section covers the commands you will use regularly.
git statusDisplays the current state of your repository.
git status
It helps you understand:
Short format:
git status -s
Example:
M README.md
?? app.js
Here, M indicates a modified tracked file, and ?? indicates an untracked file.
git addAdds 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.
git commitRecords 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.
git logDisplays 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
git diffDisplays 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
git showDisplays 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
git rmRemoves 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
git mvRenames 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.
.gitignoreA .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
secret.txt
*.log
uploads/
logs/*
!logs/README.md
git check-ignore -v .env
This shows which ignore rule matches the file.
.gitignore does not untrack existing filesIf 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.
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.
git branch
List all local and remote-tracking branches:
git branch -a
git branch feature/login
git switch feature/login
git switch -c feature/signup
Rename the current branch:
git branch -m feature/auth
Rename a different local branch:
git branch -m old-name new-name
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.
git branch --show-current
git switch --track origin/feature/login
This creates a local branch that tracks the remote branch.
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.
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.
git merge --no-ff feature/login
This creates a merge commit even when a fast-forward would be possible.
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.
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
| Marker | Meaning |
| ----------------------- | ---------------------------------------- |
| <<<<<<< HEAD | Starts the current side of the conflict. |
| ======= | Separates the two versions. |
| >>>>>>> feature/admin | Ends the incoming side. |
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.
A remote is a named reference to another repository.
GitHub repositories are commonly configured as remotes.
git remote
Show remote URLs:
git remote -v
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.
git remote set-url origin https://github.com/USERNAME/NEW-REPOSITORY.git
git remote remove origin
git remote rename origin upstream
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.
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
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.
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.
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.
Let's publish a local project to GitHub.
On GitHub:
If you already have a local project, you can leave the remote repository empty to avoid unnecessary initial-history conflicts.
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/USERNAME/REPOSITORY.git
git branch -M main
git push -u origin main
Your repository is now available on GitHub.
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.
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.
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
git clone https://github.com/USERNAME/REPOSITORY.git
cd REPOSITORY
git switch -c feature/profile-page
git add .
git commit -m "Add user profile page"
git push -u origin feature/profile-page
On GitHub, open a pull request from feature/profile-page into main.
Include:
After the required reviews and checks pass, merge the pull request using the repository's configured merge method.
git push origin --delete feature/profile-page
Many teams automatically delete feature branches after merging.
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.
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.
Use the Fork button on the original GitHub repository.
git clone https://github.com/YOUR_USERNAME/PROJECT.git
cd PROJECT
git remote add upstream https://github.com/ORIGINAL_OWNER/PROJECT.git
git remote -v
You should see origin pointing to your fork and upstream pointing to the original repository.
git switch -c fix/documentation
git add .
git commit -m "Fix installation documentation"
git push -u origin fix/documentation
Create a pull request from your fork's feature branch into the original repository's target branch.
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.
Git provides several commands for undoing changes. Choosing the right command is important because some operations can discard work or rewrite history.
git restoreDiscard 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.
git resetMoves the current branch reference to another commit, with different effects depending on the selected mode.
git reset --soft HEAD~1
Removes the latest commit from the current branch while keeping its changes staged.
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
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.
git revertCreates 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.
| 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 |
Git stash temporarily stores changes so you can switch tasks without committing incomplete work.
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.
git stash list
git stash apply
Apply a particular stash:
git stash apply stash@{1}
git stash pop
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.
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.
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.
git switch feature
git fetch origin
git rebase origin/main
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. |
git rebase --abort
git add .
git rebase --continue
git rebase --skip
Use --skip only when you intentionally want to omit the changes from the current commit.
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.
Tags identify specific commits, often to mark releases.
git tag
git tag v1.0.0
git tag -a v1.0.0 -m "Release version 1.0.0"
Annotated tags contain metadata such as the tagger, date, and message.
git show v1.0.0
git push origin v1.0.0
Push all local tags:
git push origin --tags
git tag -d v1.0.0
git push origin --delete v1.0.0
A typical release workflow is:
Semantic versioning commonly uses:
MAJOR.MINOR.PATCH
For example:
1.0.0
git reflogThe 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.
git bisectUse 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
git blameShows 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.
git cleanRemoves 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.
git worktreeAllows 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.
git archiveCreates 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.
git bundleCreates 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.
git shortlogSummarizes commits by author.
git shortlog
Show a concise author summary:
git shortlog -sn
This can help review contributions over a particular range.
Understanding Git internals helps explain why Git is reliable and how advanced commands work.
Git stores content using objects.
A blob stores file contents.
It does not store the file name or directory structure.
A tree represents a directory structure. It points to blobs and other trees.
A commit records a snapshot reference, parent commit information, author information, committer information, and a commit message.
An annotated tag is an object that points to another Git object, commonly a commit.
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
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.
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.
GitHub CLI, commonly called gh, allows you to interact with GitHub from your terminal.
Install it using the instructions on:
https://cli.github.com/
gh auth login
Check authentication status:
gh auth status
gh repo create my-project --public
Create a private repository:
gh repo create my-project --private
gh repo clone OWNER/REPOSITORY
gh pr list
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."
gh pr checkout 42
gh pr review 42
gh pr merge 42
gh repo view
The GitHub CLI supports many more commands for issues, releases, workflows, and repository management.
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/
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.
| 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. |
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.
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 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.
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.
fatal: not a git repositoryYou 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
Author identity unknownConfigure your Git identity:
git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"
remote origin already existsCheck existing remotes:
git remote -v
Update the existing URL:
git remote set-url origin https://github.com/USERNAME/REPOSITORY.git
rejected because the remote contains workThe 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.
CONFLICTGit cannot automatically combine the changes.
Check conflicted files:
git status
Resolve the conflicts, stage the files, and continue the merge or rebase.
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.
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.
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.
Small commits are easier to review, understand, test, and revert.
Examples:
feature/user-auth
fix/navbar-responsive
hotfix/payment-error
docs/api-guide
Start from an up-to-date branch to reduce unnecessary conflicts.
Keep API keys, database credentials, access tokens, and private keys out of your repository.
Pull requests provide a structured way to review and discuss changes before merging.
Configure rules that require reviews and successful automated checks before merging.
A force push can remove commits that other collaborators depend on.
Use --force-with-lease only when rewriting history is appropriate.
.gitignore updatedExclude dependencies, build artifacts, temporary files, and sensitive local configuration.
A good README should explain:
Understand git restore, git reset, git revert, and git reflog before using them on important projects.
git --version
git config --list
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git help
git init
git clone URL
git status
git remote -v
git remote add origin URL
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
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
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
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
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
git tag
git tag -a v1.0.0 -m "Release 1.0.0"
git push origin v1.0.0
git push origin --tags
The best way to learn Git is by using it in real projects.
Create a portfolio project and practice:
git initgit addgit commitgit statusgit loggit pushBuild a simple task management application.
Create branches for:
Practice merging each feature through a pull request.
Choose an open-source repository.
Practice:
Create a small application and intentionally introduce a bug.
Practice:
git bisect.git blame.git reflog.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.