1. Git Fundamentals Git is a distributed version control system (DVCS) that tracks changes in source code during software development. It allows multiple developers to work on the same project without conflicts. GitHub is a web-based platform that uses Git for version control. It provides hosting for Git repositories, collaboration features, and a graphical interface. Local Repository (Git) : Your copy of the project history on your machine. Remote Repository (GitHub) : A shared copy of the project history, typically hosted online (e.g., GitHub, GitLab, Bitbucket). Git Architecture & Flow Git operates with three main states/areas in your local environment: Working Directory (Working Tree) : The files you are currently editing. This is where you make changes. Staging Area (Index) : A temporary area where you prepare changes (snapshots) that you want to include in your next commit. Think of it as a "draft" for your commit. Local Repository (.git directory) : Where Git stores all the project's history, including commits, branches, and tags. This is the actual database for your project version control. Flow of Data: Working Directory (Unstaged Changes) Staging Area (Staged Changes) Local Repository (Committed History) git add git commit git restore git reset 2. Basic Configuration Configure user information and preferences for Git. git config --global user.name "Your Name" : Sets the name to be used in commit messages globally for all your repositories. git config --global user.email "your.email@example.com" : Sets the email to be used in commit messages globally. git config --list : Shows all current Git configurations. git config --local user.name "Project Name" : Overrides the global setting for the current repository only. This command is run inside a Git repository. Configuration Files Affected ~/.gitconfig (or C:\Users\YourUser\.gitconfig on Windows): Stores --global settings. .git/config : Stores --local settings for a specific repository. 3. Important Git Terms Explained Term Meaning Where It Exists Example/Context origin Default alias for the URL of the remote repository. Remote Added using git remote add origin <url> . Used in git push origin main . main / master Conventional name for the primary development branch. Both (Local & Remote) git branch -M main ; git push origin main . HEAD A pointer to the tip of the current branch, which is the latest commit in your current working branch. Local Moves during git checkout , git commit . Represents "where you are now". commit A snapshot of your project at a specific point in time. Identified by a unique SHA-1 hash. Local (pushed to Remote) Created with git commit -m "Message" . Contains changes from the Staging Area. branch A lightweight, movable pointer to a commit. Allows parallel development. Both (Local & Remote) git branch new-feature ; git checkout new-feature . remote A reference to a shared Git repository, typically hosted online. Remote Managed via git remote commands. E.g., origin is a remote. tag A permanent, immutable pointer to a specific commit, usually marking release points. Both (Local & Remote) git tag -a v1.0 -m "Release v1.0" . Unlike branches, tags don't move. 4. Repository Initialization git init : Initializes a new empty Git repository in the current directory. Affects: Local only. Creates: A .git subdirectory, which contains all necessary repository files (objects, refs, hooks, etc.). Your project files remain in the working directory. Use Case: Starting a new project from scratch. git clone <url> : Creates a copy of an existing remote Git repository. Affects: Local (creates a new repo) and interacts with Remote. Creates: A new directory named after the repository, initializes a .git subdirectory within it, pulls all commits and branches from the remote, and automatically sets up origin as the remote name and origin/main (or origin/master ) as the remote tracking branch. Use Case: Getting a copy of an existing project. Files Created/Managed .git/ : The core Git repository. Never manually edit files here unless you know exactly what you're doing. .gitignore : A plain text file where you list patterns of files and directories that Git should ignore (e.g., build artifacts, dependencies, sensitive config files). # Example .gitignore *.log /node_modules/ .env 5. Adding and Committing The core workflow for saving changes in Git. git add <file> : Moves changes from the Working Directory to the Staging Area . Affects: Local only (Staging Area). Explanation: Tells Git which specific changes you want to include in your next commit. You can add individual files, parts of files, or all changes. Example: git add index.html , git add . (adds all changes). git commit -m "Your commit message" : Takes the snapshot currently in the Staging Area and permanently stores it in the Local Repository as a new commit object. Affects: Local only (Local Repository). Explanation: A commit is a point in your project's history. Each commit has a unique SHA-1 hash, an author, a date, and a commit message explaining the changes. -m : Provides a short, descriptive commit message. git commit -am "Message" : A shortcut to add all tracked modified files and then commit them. Does not add new (untracked) files. States of Files Untracked: Files that are new and Git hasn't started tracking yet. (e.g., after git init , all files are untracked). Modified: Files that Git is tracking, but you've made changes to them in your Working Directory since the last commit. Staged: Modified (or new) files that have been marked to be included in the next commit (via git add ). Committed: Files that are safely stored in your local repository. git status : Shows the state of your working directory and staging area. 6. Branching & Switching Branches allow you to diverge from the main line of development and work on new features or fixes without affecting the stable code. git branch : Lists all local branches. The current branch is highlighted. git branch <new-branch-name> : Creates a new branch pointing to the current commit, but does not switch to it. Affects: Local only. git checkout <branch-name> : Switches your HEAD pointer to the specified branch. This changes your Working Directory to reflect the state of that branch. Affects: Local (Working Directory and HEAD ). git checkout -b <new-branch-name> : Creates a new branch AND switches to it (shortcut for git branch <name> then git checkout <name> ). git switch <branch-name> : A newer, more explicit command introduced in Git 2.23 for switching branches, separating concerns from git checkout (which also restores files). Affects: Local (Working Directory and HEAD ). git switch -c <new-branch-name> : Creates a new branch and switches to it. git branch -d <branch-name> : Deletes the specified local branch. Git prevents deletion if the branch has unmerged changes (use -D for force delete). Affects: Local only. git push origin --delete <branch-name> : Deletes a branch on the remote repository. Affects: Remote. How HEAD Changes HEAD is a symbolic reference to the commit where you are currently working. When you switch branches, HEAD moves to point to the tip of the new branch. Commit A -- Commit B -- Commit C (main, HEAD) \ Commit D -- Commit E (feature) If you run git checkout feature , HEAD will move from Commit C to Commit E , and your working directory will update to reflect Commit E 's files. 7. Merging Merging integrates changes from one branch into another. git merge <branch-to-merge-in> : Integrates the specified branch's history into your current branch (where HEAD is pointing). Affects: Local only (until pushed). Merge Strategies Fast-Forward Merge: Occurs when there's a linear path from the current branch's tip to the branch being merged. Git simply moves the current branch pointer forward to the target branch's latest commit. No new commit is created. History remains linear. A B C (main) + C D E (feature) -> C D E (main) Three-Way Merge (Recursive Merge): Occurs when the histories of the two branches have diverged. Git finds a common ancestor commit and then creates a new "merge commit" that combines the changes from both branches. A new merge commit is created. This preserves the history of both branches explicitly. A B (common ancestor) C (feature) D (main) -> A B C D M (merge commit) Merge Conflicts Why they occur: When Git tries to merge two branches, and both branches have modified the same part of the same file, Git cannot automatically decide which change to keep. How to resolve: Git marks the conflicting sections in the file with special markers ( <<<<<< HEAD , ======= , >>>>>> <branch-name> ). Manually edit the file to resolve the conflict (choose one version, combine them, or write new code). Remove the conflict markers. git add <conflicted-file> to mark it as resolved. git commit (Git will usually pre-fill a merge commit message). git merge --abort : Stops the merge process and reverts your repository to the state before the merge attempt. 8. Rebasing Rebasing is the process of moving or combining a sequence of commits to a new base commit. It rewrites project history. git rebase <base-branch> : Moves your current branch's commits to the tip of the <base-branch> . How it works: Git finds the common ancestor, then "rewinds" your current branch's commits, applies the commits from the <base-branch> , and then reapplies your branch's commits on top. Affects: Local only (until pushed). Rewrites history! A B C (feature) D (main) -> A B D (main) C' (feature) Rebase vs. Merge Merge: Preserves history exactly as it happened. Creates a merge commit, which can make history look "messy" with many merge commits. Safer for shared branches because it doesn't rewrite history. Rebase: Creates a linear, "cleaner" history by rewriting commits. Original commits are destroyed and re-created with new SHA-1 hashes. DO NOT rebase commits that have already been pushed to a shared remote repository , as it can cause conflicts for other collaborators. Best used for cleaning up your own local feature branches before merging them into a shared branch. Rebase Workflow git rebase --continue : After resolving a conflict during rebase, stage the file(s) and then run this to continue. git rebase --abort : Stops the rebase process and reverts your branch to its state before the rebase started. git rebase -i <commit-hash> or git rebase -i HEAD~N : Interactive rebase. Allows you to reorder, squash, edit, or drop commits within a specified range. Powerful for cleaning up history. 9. Reset, Revert & Restore Different ways to undo changes in Git. git reset Moves the HEAD pointer and optionally changes the Staging Area and Working Directory. Local-only action. Syntax: git reset [--soft | --mixed | --hard] <commit> <commit> : Can be a commit SHA, a branch name, HEAD , HEAD~1 (one commit before HEAD), etc. Modes: --soft : Moves HEAD to the specified commit. Keeps the Staging Area and Working Directory unchanged. Changes between the old HEAD and the new HEAD are now "staged changes". Use Case: Undo the last commit but keep changes staged for a new commit. Example: git reset --soft HEAD~1 --mixed (Default): Moves HEAD to the specified commit. Unstages changes (moves them from Staging Area back to Working Directory). Keeps the Working Directory unchanged. Changes between the old HEAD and the new HEAD are now "unstaged changes". Use Case: Undo the last commit and unstage the changes, to re-evaluate or re-commit. Example: git reset HEAD~1 ( --mixed is default) --hard : Moves HEAD to the specified commit. Resets the Staging Area to match the new HEAD . Resets the Working Directory to match the new HEAD . DANGEROUS: All uncommitted changes in the Working Directory and Staging Area are permanently lost. Use Case: Discard all local changes and commits since a certain point. Example: git reset --hard origin/main (to match remote) git revert <commit> Creates a new commit that undoes the changes introduced by the specified <commit> . Affects: Local (creates a new commit), and subsequently Remote once pushed. Explanation: It does not erase history; it adds a new history entry that reverses previous changes. This is crucial for shared branches. Use Case: Undo changes that have already been pushed to a shared remote repository. It's safe because it doesn't rewrite history. Example: git revert <commit-hash-to-undo> git restore (Introduced in Git 2.23) Restores files in the Working Directory or Staging Area to a previous state. Separates file restoration from branch switching ( git checkout ). git restore <file> : Discards changes in the Working Directory for <file> . Restores it to the state in the Staging Area. If <file> is not in the Staging Area, it restores it to the HEAD commit. Affects: Local (Working Directory). Use Case: Undo local modifications to a file. git restore --staged <file> : Unstages changes for <file> . Moves it from the Staging Area back to the Working Directory. Affects: Local (Staging Area). Use Case: "Un-add" a file that was mistakenly staged. git restore --source=<commit> <file> : Restores <file> in the Working Directory to its state at the specified <commit> . Affects: Local (Working Directory). Use Case: Get an older version of a file without changing history. 10. Remote Operations Interacting with remote repositories (e.g., GitHub). git remote add origin <url> : Adds a new remote repository to your local Git configuration. origin is the conventional name for the primary remote. Affects: Local (updates .git/config ). Example: git remote add origin https://github.com/user/repo.git git push origin main : Uploads your local commits from the main branch to the main branch on the origin remote. Affects: Both Local (tracks remote) and Remote (updates history). Explanation: origin refers to the remote alias, main refers to the local branch you're pushing, and also the remote branch you're pushing to. First push: Use git push -u origin main to set the upstream tracking branch, so subsequent pushes can just be git push . Force push ( git push --force-with-lease or git push -f ): Overwrites remote history with your local history. DANGEROUS on shared branches as it can erase collaborators' work. Use with extreme caution. git pull origin main : Fetches changes from the main branch of the origin remote and then merges them into your current local branch. Affects: Both Local (updates history and working dir) and Remote (fetches from). Equivalent to: git fetch origin main followed by git merge origin/main . Use Case: Update your local repository with the latest changes from the remote. git fetch origin : Downloads commits, files, and refs from the origin remote repository into your local repository. Crucially, it does NOT merge or modify your local working directory. Affects: Local only (updates remote-tracking branches like origin/main ). Use Case: See what others have pushed without integrating it into your current work. You can then compare main with origin/main . git remote -v : Lists the remote repositories you have configured, along with their URLs. Affects: Local (reads config). 11. Stashing Temporarily saves changes that are not ready to be committed, allowing you to switch branches or perform other operations. Stash data is stored locally in the .git/refs/stash file. git stash (or git stash save "message" ): Saves your current uncommitted changes (both staged and unstaged) to a temporary "stash" and reverts your Working Directory to the state of the HEAD commit. Affects: Local (Working Directory, Staging Area, and .git data). What happens: Your Working Directory becomes clean, as if you just committed. git stash list : Shows a list of all stashed changes. Affects: Local (reads .git data). git stash apply <stash@{n}> : Applies the stashed changes back to your Working Directory. The stash remains in the stash list. If no <stash@{n}> is specified, it applies the most recent stash ( stash@{0} ). Affects: Local (Working Directory). git stash pop <stash@{n}> : Applies the stashed changes and then immediately removes it from the stash list. Affects: Local (Working Directory and .git data). Use Case: Typically preferred when you're done with a stash. git stash drop <stash@{n}> : Removes a specific stash entry from the stash list without applying it. Affects: Local ( .git data). git stash clear : Removes all stash entries. Affects: Local ( .git data). 12. Cherry-Picking Applies specific existing commits from one branch onto another branch. git cherry-pick <commit-hash> : Takes the changes introduced by the specified <commit-hash> and creates a new commit with those changes on your current branch. Affects: Local only (until pushed). Use Cases: Hotfixes: Apply a critical fix from a development branch directly to a stable release branch without merging the entire development branch. Selective Merges: Pick individual commits instead of merging an entire branch. Conflict Handling: If a conflict occurs, resolve it, git add <file> , then git cherry-pick --continue . To abort, git cherry-pick --abort . 13. Tagging Tags are used to mark specific points in history as important, typically for release versions. Lightweight Tags: A simple pointer to a specific commit. Like a branch that doesn't move. git tag <tag-name> : Creates a lightweight tag on the current commit. Annotated Tags: Full Git objects, stored in the Git database. They contain a tagger name, email, date, and a message. They are generally recommended for releases. git tag -a v1.0 -m "Version 1.0 Release" : Creates an annotated tag. git tag : Lists all local tags. git show <tag-name> : Shows information about a specific tag and its associated commit. Pushing Tags: By default, git push does not push tags. git push origin <tag-name> : Pushes a specific tag to the remote. git push origin --tags : Pushes all local tags to the remote. Affects: Both Local and Remote (once pushed). Deleting Tags: git tag -d <tag-name> : Deletes a local tag. git push origin --delete <tag-name> : Deletes a remote tag. 14. Undoing Local & Remote Changes Undoing Locally (Before Pushing): git reset : ( --soft , --mixed , --hard ) is your primary tool for undoing local commits or unstaging changes. It rewrites local history. git restore : For discarding changes in the Working Directory or un-staging files. Does not affect commit history. Undoing Remotely (After Pushing): git revert <commit> : The safest way to undo a pushed commit. It creates a new commit that explicitly reverses the changes of the target commit. This preserves history and doesn't affect other collaborators' work. git push --force-with-lease : (or -f ) can "undo" remote changes by overwriting the remote branch with your local one. Extremely dangerous if others have based work on the remote branch, as it can erase their commits. Only use this if you are absolutely sure no one else has pulled those commits, or if you can coordinate with your team. 15. Logs and Inspection Tools to view and understand your repository's history. git log : Displays the commit history, showing commit hash, author, date, and message. Affects: Local (reads .git data). git log --oneline : Shows a condensed view of the log, one commit per line with abbreviated hash and message. git log --oneline --graph --decorate : Visualizes the commit history as a graph, showing branches and merges. Very useful for understanding branch structures. git log -p : Shows the diff (patch) introduced by each commit. git log --author="Your Name" : Filters log by author. git log --since="2 weeks ago" : Filters log by date. git reflog : Shows a log of all actions that modified HEAD in your local repository. This includes checkouts, commits, resets, merges, rebases, etc. Crucial for recovering lost commits! Even if you git reset --hard and seemingly lose commits, reflog can often show you where HEAD was before, allowing you to recover using git reset <reflog-entry> . Affects: Local (reads .git data). git show <commit-hash> : Displays the metadata and changes (diff) for a specific commit. Affects: Local (reads .git data). git diff : Shows changes between: Working Directory and Staging Area ( git diff ) Staging Area and last commit ( git diff --staged or git diff --cached ) Working Directory and last commit ( git diff HEAD ) Two commits ( git diff <commit1> <commit2> ) 16. Merging Conflicts (Detailed) Merge conflicts happen when Git cannot automatically reconcile changes between two branches. Conflict Markers When a conflict occurs, Git modifies the conflicting files with special markers: <<<<<< HEAD This is the content from my current branch (HEAD). ======= This is the content from the branch I'm merging (e.g., feature-branch). >>>>>>> feature-branch <<<<<< HEAD : Marks the beginning of the conflicting changes from your current branch. ======= : Separates the changes from your current branch and the incoming branch. >>>>>>> <branch-name> : Marks the end of the conflicting changes from the incoming branch. Resolution Steps Identify Conflicts: git status will show which files have conflicts (unmerged paths). Edit Files: Open the conflicting files in your editor. Manually remove the conflict markers and decide which version of the code to keep, or combine them as needed. Add Resolved Files: After editing, run git add <conflicted-file> for each resolved file. This tells Git the conflict is resolved for that file and stages the result. Commit: Once all conflicts are resolved and added, run git commit . Git will automatically provide a merge commit message; you can modify it or save it as is. Abort: If you get overwhelmed or want to restart, use git merge --abort (or git rebase --abort ) to go back to the state before the merge/rebase attempt. 17. Common Workflows A typical sequence for starting a project, making changes, and pushing them. # Scenario: Start a new project, commit, and push to GitHub. # 1. Initialize a new Git repository in your project directory. git init # Affects: Local. Creates the .git/ directory. # 2. Add all current files to the staging area. git add . # Affects: Local (Staging Area). Prepares all untracked/modified files for commit. # 3. Commit the staged changes to your local repository. git commit -m "Initial commit of project files" # Affects: Local (Local Repository). Creates the first commit. # 4. (Optional but recommended) Rename the default branch from 'master' to 'main'. git branch -M main # Affects: Local. Renames the current branch. # 5. Link your local repository to a remote repository on GitHub (or other hosting). # Replace <your-github-username>/<repo-name> with your actual values. git remote add origin https://github.com/your-github-username/your-repo-name.git # Affects: Local (updates .git/config). 'origin' is now an alias for the URL. # 6. Push your local 'main' branch to the 'origin' remote. # The -u flag sets 'origin/main' as the upstream for your local 'main' branch. # This means future 'git push' and 'git pull' commands can be run without specifying 'origin main'. git push -u origin main # Affects: Both Local (sets upstream) and Remote (uploads commits, creates remote branch). # Data flow: Local Repository (commits) --> Remote Repository (origin/main) After the initial setup: # 1. Make changes to your files. # 2. Check status to see modified/untracked files. git status # 3. Stage your changes. git add . # 4. Commit your changes. git commit -m "Added new feature X" # 5. Pull any changes from remote before pushing (good practice to avoid conflicts). git pull origin main # Affects: Both. Fetches remote changes, merges into local. # Data flow: Remote (origin/main) --> Local (Working Dir, Staging Area, Local Repo) # 6. Push your changes to the remote. git push # Affects: Both. Uploads new local commits to remote. # Data flow: Local Repository --> Remote Repository 18. Collaboration Forking: Creating a personal copy of someone else's repository on a platform like GitHub. You make changes in your fork and then propose them back to the original (upstream) repository via a Pull Request. Pull Requests (PRs / Merge Requests): A feature of platforms like GitHub/GitLab where you propose your changes (a branch) to be merged into another branch (often main ) in the original repository. It allows for code review and discussion before integration. Merging Strategies in PRs: Standard Merge Commit: Creates a merge commit, preserving all commit history from the feature branch. (Similar to 3-way merge). Squash Merge: Combines all commits from the feature branch into a single new commit on the target branch. Creates a clean, linear history. Rebase Merge: Reapplies the feature branch's commits directly onto the target branch's tip, creating a linear history without a merge commit. git fetch upstream : In a forking workflow, upstream is typically the alias for the original repository you forked from. This command fetches changes from the original repository (which you don't directly push to) into your local repository, updating your upstream/main (or upstream/master ) remote-tracking branch. Use Case: Keep your local fork updated with the latest changes from the original project. 19. Cleaning and Maintenance .gitignore : Specifies intentionally untracked files that Git should ignore. Example: node_modules/ , *.log , .env . git clean -n : Shows which untracked files would be removed. (Dry run) Affects: Local ( Working Directory - reads). git clean -f : Removes untracked files from the Working Directory. Affects: Local (Working Directory - deletes files). git clean -f -d (or git clean -fd ): Removes untracked files and untracked directories. Affects: Local (Working Directory - deletes files/dirs). git gc (Garbage Collect): Cleans up unnecessary files and packs local repository data to optimize performance. Usually runs automatically in the background. Affects: Local ( .git directory). .gitattributes : A file that allows you to define attributes for paths in your repository, such as how Git should handle line endings ( text=auto , text eol=lf ), diff strategies, or binary file detection. Example: *.txt text eol=lf , *.jpg binary . 20. Cheatsheet Summary Table Command Description Local/Remote Impact Example/Use Case git init Create new local Git repo. Local Starting a new project. git clone <url> Copy existing remote repo to local. Both (Local created, Remote consulted) Getting a copy of an existing project. git add . Stage all changes for next commit. Local (Staging Area) Prepare files for committing. git commit -m "Msg" Save staged changes to local repo. Local (Repo) Create a snapshot of your work. git status Show working directory & staging area state. Local See what's modified, staged, or untracked. git log --oneline View commit history (brief). Local Quick overview of commits. git branch <name> Create new branch. Local Start new feature work. git checkout <name> Switch to another branch/commit. Local (HEAD, Working Dir) Change context of work. git merge <branch> Combine history of two branches. Local (Repo) Integrate feature into main. git rebase <branch> Reapply commits on top of another base tip. Local (Repo) - Rewrites history! Clean up local feature branch history before merge. git reset --hard HEAD~1 Discard last commit and all local changes. Local (Repo, Staging, Working Dir) - DANGEROUS Completely undo recent local work. git revert <commit> Create new commit to undo specific commit. Both (Local, then Remote via push) Safely undo a pushed commit. git restore <file> Discard changes in working directory for a file. Local (Working Dir) Undo accidental file edits. git restore --staged <file> Unstage a file. Local (Staging Area) Remove file from next commit. git remote add origin <url> Connect local repo to remote. Local (config) Link your local project to GitHub. git push origin main Upload local commits to remote. Both (Local → Remote) Share your committed work. git pull origin main Fetch & merge from remote to local. Both (Remote → Local) Get latest updates from collaborators. git fetch origin Download remote changes without merging. Local (updates remote-tracking branches) See remote updates before integrating. git stash Temporarily save uncommitted changes. Local (Stash stack) Clean working dir to switch branches quickly. git stash pop Apply & remove most recent stash. Local (Working Dir, Stash stack) Restore stashed work. git cherry-pick <commit> Apply a specific commit from another branch. Local (Repo) Apply a hotfix or selective change. git tag -a v1.0 -m "Msg" Create an annotated tag. Local (pushed to Remote explicitly) Mark a release version. git reflog View history of HEAD movements. Local Recover "lost" commits after reset/rebase. git clean -fd Remove untracked files and directories. Local (Working Dir) - DANGEROUS Clean up build artifacts or temporary files.