Skip to content

Git & GitHub Overview

What is Git?

Git is a distributed version control system that tracks changes to files over time. It allows multiple developers to collaborate on projects without overwriting each other’s work.

Why Git is needed:

  • Version history: Maintains a complete history of changes, allowing you to revert to previous versions.
  • Collaboration: Enables multiple people to work on the same project simultaneously.
  • Branching: Supports creating separate branches for developing features without affecting the main codebase.
  • Offline work: Allows working locally without constant connection to a central server.
  • Backup: Serves as a backup system for your code and project files.

Install Git

Git is available on all major operating systems. You can download it from the Git website.

Check if you already have it and what version:

Terminal window
git --version

Git Config

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

What is GitHub?

GitHub is a web-based hosting service for Git repositories. It adds a visual interface and additional features on top of Git’s functionality.

GitHub Features:

  • Repository hosting: Stores Git repositories in the cloud.
  • Pull requests: Facilitates code review and discussion before merging changes.
  • Issues tracking: Manages bugs, enhancements, and tasks.
  • Project management: Provides boards and tools to organize work.
  • Actions: Enables automated workflows and CI/CD pipelines.
  • Collaboration tools: Offers features like discussions, wikis, and team management.

Basic Git Commands

Here are some fundamental commands you’ll use often.

Initialize a repository (git init)

Turns your current directory into a Git repository.

Terminal window
git init
  • This will create a new hidden directory called .git in your project folder.
  • This .git directory contains all the repository’s tracking information and history. Don’t delete it!

Check the status (git status)

Shows the current state of your working directory and staging area.

Terminal window
git status

Add files to staging (git add)

Tells Git you want to track changes in specific files for the next commit. This is called “staging” changes.

Terminal window
# Add a specific file
git add <file-name.js>
# Add all changed files in the current directory and subdirectories
git add .

Commit changes (git commit)

Saves the currently staged changes to the repository’s history. Think of it as creating a checkpoint or snapshot of your project.

Terminal window
git commit -m "Your descriptive commit message"

Push changes (git push)

Uploads your local commits to a remote repository (like GitHub), making them available to collaborators.

  1. Connect to GitHub (if needed): It’s highly recommended to connect using SSH keys for security and convenience. You can generate these and add them in your GitHub account settings. See the official documentation: Connecting to GitHub with SSH.

  2. Link Local Repo to Remote: If you created the repo locally (git init), you need to tell Git where the remote version lives (usually on GitHub). You typically only do this once per project. origin is the standard name for your main remote repository.

    Terminal window
    git remote add origin <repository-url-from-github.git>
  3. Push Your Commits: The first time you push a new branch (like main), use -u to set the “upstream” tracking relationship. This tells Git where to push to and pull from for this branch by default.

    Terminal window
    # First push for the main branch
    git push -u origin main

    After the first push, you can usually just use:

    Terminal window
    # Push subsequent commits on the current branch
    git push

See Commit History (git log)

Displays the commit history for the current branch.

Terminal window
git log
# Show a condensed, one-line summary of each commit
git log --oneline

Ignore Files (.gitignore)

Sometimes you have files or directories you don’t want Git to track (like temporary files, dependency folders, or secret keys).

  1. Create the file: In the root directory of your project:
    Terminal window
    touch .gitignore
  2. Add patterns: List the files or directories you want Git to ignore, one per line.
    # Example .gitignore file
    # Dependency directories
    node_modules/
    vendor/
    # Build output
    dist/
    build/
    # Files with sensitive information
    .env
    *.pem
    secrets.json
    # OS-generated files
    .DS_Store
    Thumbs.db

Branching (git branch, git checkout, git merge)

Branches allow you to work on different features or fixes in isolation without affecting the main (main or master) codebase until you’re ready.

See Branches

Terminal window
git branch

The asterisk * indicates the branch you are currently on (where HEAD is pointing).

* main
new-feature

Create a Branch

Terminal window
# Create a new branch named 'new-feature'
git branch new-feature
# Switch to the 'new-feature' branch to start working on it
git checkout new-feature

Or, create and switch in one command:

Terminal window
# Create branch 'another-feature' and switch to it immediately
git checkout -b another-feature

Rename a Branch

Terminal window
# Rename 'old-name' to 'new-name' (make sure you're not currently on 'old-name')
git branch -m old-name new-name

Switch Branches

Terminal window
# Switch back to the main branch
git checkout main
# Switch to an existing feature branch
git checkout new-feature

Merge a Branch

Combines the changes from one branch into your current branch.

  1. Switch to the receiving branch: Usually main.
    Terminal window
    git checkout main
  2. Merge the feature branch into main:
    Terminal window
    git merge new-feature

Conflicts (git merge conflicts)

A conflict happens when you try to merge branches that have changed the same lines in the same file differently. Git can’t automatically decide which change is correct.

Git will mark the conflicted areas in the file like this:

<<<<<<< HEAD
// Changes from your current branch (e.g., main)
function hello() {
console.log("Hello from main branch!");
}
=======
// Changes from the branch you are merging (e.g., new-feature)
function hello() {
console.log("Hello from the new feature!");
}
>>>>>>> new-feature

To resolve:

  1. Open the conflicted file(s) in your editor.
  2. Manually edit the file to remove the conflict markers (<<<<<<<, =======, >>>>>>>) and combine the changes the way you want them.
  3. Save the file.
  4. git add <resolved-file-name> the file(s) you fixed.
  5. git commit to finalize the merge commit.

See Differences (git diff)

Shows the differences between various states in your repository (commits, branches, working directory, staging area).

Basic Usage

Terminal window
# Show changes in your working directory NOT yet staged for commit
git diff
# Show changes that ARE staged for the next commit
git diff --staged
# (or git diff --cached)
# Show differences between two branches
git diff main..new-feature
# Show differences for specific files between branches
git diff main..new-feature -- path/to/file1.js path/to/another/file.txt
# Show changes introduced between two specific commits
git diff <commit-hash-1> <commit-hash-2>

Understanding Diff Output

diff --git a/file.js b/file.js
index abc123..def456 100644
--- a/file.js <- The 'a' version (before changes)
+++ b/file.js <- The 'b' version (after changes)
@@ -1,5 +1,5 @@ // Line numbers context: -line#,num_lines +line#,num_lines
function greeting() {
- console.log("Hello"); // Line starting with '-' was removed from 'a'
+ console.log("Hi"); // Line starting with '+' was added in 'b'
console.log("Greeting completed"); // Unchanged line for context
}

Stashing Changes (git stash)

Temporarily saves your uncommitted local changes (both staged and unstaged) so you can switch branches or work on something else without committing incomplete work.

Terminal window
# Save current changes to the stash "stack"
git stash
# Save changes with a descriptive message
git stash save "WIP: Refactoring login form"
# See the list of stashed changes
git stash list
# Output might look like:
# stash@{0}: WIP on main: abc123d Initial commit
# stash@{1}: WIP: Refactoring login form
# Apply the most recent stash (stash@{0}) and keep it in the list
git stash apply
# Apply a specific stash (e.g., the second one in the list)
git stash apply stash@{1}
# Apply the most recent stash AND remove it from the stash list
git stash pop
# Remove a specific stash without applying it
git stash drop stash@{1}
# Remove ALL stashed changes (use with caution!)
git stash clear

Common Use Case: Switching Branches