Sitemap
Vipin Kumar

Vipin Kumar

Git & GitHub Concepts

18 min readMay 27, 2026

--

Press enter or click to view image in full size

Table of Contents

  1. What is Git & GitHub
  2. Key Concepts
  3. Initial Setup
  4. Working with Git
    1. Set up the repository
    2. Remote (The Cloud Server)
    3. Stage the files (The Staging Area)
    4. Commit the files (Saving a Snapshot)
    5. Git Revert (The Safe Undo Option)
    6. Upstream (Tracking Links)
    7. Viewing History & Logs
    8. Inspecting Changes (Diff) and Time Travel
    9. Git Tags (Marking Milestones)
    10. Git Stash (The Temporary Storage Drawer)
    11. Git Branch
    12. Git Merge (Combining Timelines)
    13. Rebase (Rewriting History)
    14. Git Cherry-pick (Precision Plucking)
    15. Git Bisect (The Binary Search Debugger)
    16. Git Reflog (The Emergency Safety Net)
    17. Git Worktrees (Multi-Tasking)
  5. The Repository Gatekeeper: .gitignore
  6. Performance & Maintenance
  7. GitHub Secrets

1. What is Git & GitHub?

Git is a mature, distributed version control system (DVCS) designed to track changes in source code during software development. It was created by Linus Torvalds in 2005, and has been maintained by Junio Hamano since then. Unlike older centralized systems, every developer’s working copy contains a complete, independent clone of the project’s entire history and metadata. It utilizes a content-addressable storage model based on cryptographic hashing (SHA-1/SHA-256) to ensure data integrity and prevent history tampering. Git’s architecture heavily optimizes for non-linear development workflows by treating branches as lightweight, mutable pointers to specific commits, enabling rapid, isolated feature development, merging, and distributed collaboration across decoupled engineering teams.

GitHub is a cloud-based hosting platform built on top of the Git version control system. It has been owned by Microsoft since 2018. While Git is the local tool that tracks your code changes on your computer, GitHub acts as the remote, centralized hub where teams store their repositories, collaborate, and share code. It enhances Git by providing a web-based graphical interface and powerful collaboration tools — such as Pull Requests for code reviews, issue trackers for project management, automated testing pipelines (GitHub Actions), and access controls.

2. Key Concepts

  • Repository: A folder where Git tracks your project and its history using .git metadata directory.
  • Clone: A local duplication of a remote repository, including all files, branches, refs, and the full commit history log.
  • Fork: A server-side copy of a repository (typically hosted on platforms like GitHub) that exists independently of the original, allowing you to freely modify code and propose changes back via pull requests.
  • Origin: The default alias assigned to the primary remote repository URL from which the project was cloned.
  • Upstream: The designated tracking relationship binding a local branch to a specific remote branch, dictating where git pull and git push exchange data by default.
  • Untracked: Files within your working directory that have not been explicitly added to Git’s index and are completely ignored by the version tracking system.
  • Tracked: Files recognized by Git that exist in the database history and are monitored for changes across three distinct cycles: Unmodified, Modified, or Staged.
  • Stage (The Index / Cache): A binary staging area file that prepares and shapes the exact content snapshot that will be safely recorded in the next commit.
  • Commit: A cryptographic snapshot (immutable SHA hash) of your staged changes representing a permanent structural point in the repository timeline, paired with author metadata and parent pointers.
  • Stash: A temporary shell storage stack used to cleanly shelve dirty, uncommitted local modifications (both staged and unstaged) so you can switch branches without losing work.
  • Tag: An immutable, static reference pointer pointing directly to a specific commit — most commonly utilized to mark software release versions (e.g., v1.0.0).
  • Branch: A lightweight, highly mutable reference pointer that automatically glides forward to the newest commit whenever a new change is logged on that timeline.
  • HEAD: A dynamic pointer referencing the active commit your current working directory is anchored to. By default, it points to a local branch name, but can drop into a “detached HEAD” state if checked out directly to a specific commit hash.
  • Fetch: Downloads all updated tracking refs, objects, and commits from a remote repository into your local .git cache without altering or overwriting your active working files.
  • Pull: A compound command that runs git fetch to download remote data and immediately executes a git merge or git rebase to integrate those changes into your current local branch.
  • Push: Uploads local branch commits and updates corresponding tracking references on a remote repository server.
  • Merge: The process of combining history chains from two separate branches. It creates a dedicated “merge commit” with two parent pointers to preserve the historical context of both timelines.
  • Fast-Forward Merge: An optimization triggered when the target branch has no new intervening commits. Instead of creating a new merge commit, Git simply slides the target branch pointer directly forward to match the source branch head.
  • Merge Conflict: A state triggered when Git encounters competing modifications on the exact same lines of code within a file across two converging branches, pausing execution until a developer manually chooses which blocks to retain.
  • Rebase: Reshapes history by taking a sequence of commits from a branch, lifting them, and re-applying them sequentially onto the tip of a completely different base commit. This creates a clean, linear project history but rewrites commit hashes.
  • The Three Trees: The underlying architecture of Git’s local state engine consisting of the Working Directory (sandbox files on your disk), the Index (the staging environment), and the HEAD (the last committed state). Understanding how data travels through these three boundaries is vital for debugging.
  • Cherry-pick: The ability to append a single specific commit from an entirely different branch and cleanly apply it as a new commit onto your current active branch, ignoring the rest of that branch’s history.
  • Squash: An operation (typically done during an interactive rebase) that condenses a fragmented series of small, intermediate commits into a single, clean commit with a unified message before merging it into production code.
  • Reflog (Reference Log): A local emergency safety net database that records every single pointer movement of HEAD and local branches. It allows you to recover deleted branches or silently undo disastrous rebases by locating orphaned commits that no longer appear in standard history logs.

3. Initial Setup

When you first install Git, you need to introduce yourself. Git attaches this name and email to every single commit you make so your team knows who wrote the code. If you make a typo or mistake, just rerun the command with the correct value.

git config --global user.name "Your name"
git config --global user.email "you@example.com"
  • Use --system to set the value for every user on your computer.
  • Use --global to set the value for every repository on your computer.
  • Use --local (the default) to set it only for the current repository.

Older versions of Git used master as the default starting branch. You can change this so every new project you start automatically names its main branch main.

git config --global init.defaultbranch main

You can enable colorization of command line output that highlights modified files in red and staged files in green when you check your work.

git config --global color.ui auto

You can view your config using:

git config --list

If you accidentally configured a setting you no longer want (like setting a bad default text editor), you can completely erase that line using --unset:

git config --global --unset code.editor

Handle merge conflict using visual tool instead of standard text editor.

# Configure your system to leverage VS Code as your default merge engine 
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Launch your configured tool automatically when a merge conflict stalls
git mergetool

4. Working with Git

1. Set up the repository

To start tracking a project with Git, you need to create a folder and initialize it.

mkdir myproject  # Create a new project folder 
cd myproject # Go inside that project folder
git init # Turn this folder into a Git repository

Git creates a hidden folder named .git inside your project where it stores all history. To see the current status of your files (whether they are modified, untracked, or ready to save), run:

git status

2. Remote (The Cloud Server)

A Remote is simply a version of your project repository hosted on the internet or a secure cloud network (such as GitHub, GitLab, or Bitbucket). It allows multiple engineers to sync their independent local histories.

# Link your local repo to a brand new, empty repository on GitHub: 
git remote add origin git@github.com:your-username/your-repo.git
# View a list of all remote servers currently linked to your project:
git remote -v

3. Stage the files (The Staging Area)

When you create new files, Git marks them as untracked (it sees them but is ignoring them). To tell Git you want to include these files in your next save, you must stage them.

git add <file-name>   # Stage a specific file
git add . # Stage all new, changed, and deleted files in the current folder
git add --all # Stage all files across the entire project

If you accidentally staged a file that you aren’t ready to save yet, you can pull it out of the staging area without losing your code changes:

git restore --staged <file-name>

4. Commit the files (Saving a Snapshot)

Committing is like saving a permanent checkpoint in a video game. Every commit needs a clear description message.

git commit -m "your message"    # Fast save with a single-line message
git commit # Opens a text editor for long, multi-line messages
git commit --no-edit # Use previous commit message
git commit -a -m "your message" # Shortcut: Automatically stages modified files & commits them at once

If you committed too early and want to take it back, you can move the timeline backward. Using --soft turns the commit back into staged changes, --mixedremove commits and unstage the changes, and --hard removes commit, staged changes and file edits.

git reset --soft HEAD~2    # Move branch back 2 commits, keep changes staged
git reset --mixed HEAD~2 # Move back 2 commits, changes unstaged (default)
git reset --hard HEAD~2 # Move back 2 commits, lose all changes

All three modes:

  • Move the current branch’s pointer to the specified commit
  • Update HEAD to point to that commit
  • Rewrite branch history (destructive on shared branches)

5. Git Revert (The Safe Undo Option)

If you discover a bug in a commit that has already been pushed to GitHub and pulled down by your team, running git reset --hard will scramble their commit history. When they try to pull updates, Git will encounter conflicting timelines, resulting in broken local histories and manual cleanups. git revert leaves the historical timeline intact. If your target commit added a line of code, the revert commit deletes it; if the target commit deleted a file, the revert commit restores it.

git revert <commit-hash-to-undo>
git revert -n <commit-hash> # To revert a commit without automatically creating a save checkpoint

6. Upstream (Tracking Links)

An upstream branch is a dedicated link established between a local branch on your computer and its matching partner branch up on a remote server (like GitHub). Setting this link tells Git exactly where to push or fetch data when you type a short command like git pull.

# Set the link the very first time you push a brand new branch:
git push --set-upstream origin feature-login
# Shortcut equivalent using "-u":
git push -u origin feature-login

Once this link is set up once, you will never need to type the full location again. For the rest of that branch’s life, you can just run git push or git pull.

7. Viewing History & Logs

Git keeps a detailed journal of everything that has ever happened.

git log                      # Detailed list of all commits (Author, Date, Message)
git log --oneline # Ultra-clean, one-line summary of your history
git log --stat # Shows which files were changed and how many lines were added/deleted
git log --author="Alex" # Filter history to only show commits made by "Alex"
git log --since="2 weeks ago" # Filter history to show only recent work

Navigating the Log: If your history is long, Git will pause the screen.

  • Type / followed by a word (like /fix) and press Enter to search.
  • Press n to jump to the next matching word.
  • Press q to safely exit the log screen and return to your terminal.

8. Inspecting Changes (Diff) and Time Travel

Before you save your work, it is wise to see exactly what lines of code you added or deleted.

git diff                     # See changes you made that are NOT yet staged
git diff --staged # See changes that ARE staged and ready to be committed
git diff commit1_id commit2_id # Compare the differences between two specific moments in history

To see the exact code changes and author details of any specific commit from your log, copy its unique ID hash and use:

git show <commit-id>

If you want to view your project exactly as it looked in the past, you can jump back in time:

git checkout <commit-id>
git checkout main # To return safely back to your absolute newest work
git checkout <commit-id> <file-name> # Restore a file from a specific commit

9. Git Tags (Marking Milestones)

Tags are permanent bookmarks used to lock down important points in your project’s history, most commonly software releases (e.g., v1.0.0).

Get Vipin Kumar’s stories in your inbox

Join Medium for free to get updates from this writer.

Types of Tags:

  • Lightweight Tag: A simple pointer directly to a commit. Think of it as a private local bookmark.
  • Annotated Tag: A full Git object that stores the creator’s name, email, date, and a specific message. Always use these for public releases.
git tag v1.0                             # Create a lightweight tag at your current commit
git tag -a v1.0 -m "Release version 1.0" # Create an annotated tag with a message
git tag v1.1 <commit-id> # Tag an older commit using its short ID has
git tag # List all tags in the repository
git show v1.0 # View details about a tag and its matching commit

By default, tags stay on your local computer. You must explicitly push them to your server.

git push origin v1.0                   # Push a single specific tag to GitHub
git push --tags # Push all your local tags to GitHub at once
git tag -d v1.0 # Delete a tag from your local computer
git push origin --delete v1.0 # Delete a tag from your remote repository
git tag -f v1.0 <new-commit-hash> # Move the tag locally
git push --force origin v1.0 # Force-update the tag on GitHub

Tagging Best Practices:

  • Only tag your code after it passes all unit tests and is ready for production.
  • Use standard semantic versioning formats like v1.0.0 (Major.Minor.Patch).

10. Git Stash (The Temporary Storage Drawer)

If you are halfway through a feature and need to drop everything to fix an urgent bug on a different branch, you cannot commit broken code. git stash lets you shelve your messy, uncommitted changes safely so you can switch tasks.

git stash                              # Quick stash (saves tracked files)
git stash push -m "WIP: homepage UI" # Stash with a clear description message
git stash list # View your stack of saved stashes
git stash show # Show a brief summary of changes in the latest stash
git stash show -p # Show the exact line-by-line code changes in the latest stash

Stashes are saved like a stack of plates. The newest stash sits at the top as stash@{0}, the one before it is stash@{1}, and so on.

git stash apply                        # Restore the newest stash but keep a copy in the locker
git stash apply stash@{1} # Restore a specific older stash from your list
git stash pop # Restore the newest stash AND delete it from the locker at the same time
git stash drop stash@{0} # Delete one specific stash
git stash clear # WIPE OUT all stashes permanently
git stash branch feature-rescue stash@{0} # Create a new branch and immediately apply your stash to it

11. Git Branch

Branches allow you to step away from the stable, main code line to build features or test wild ideas in isolation without breaking the project for your team.

git branch feature-login               # Create a new branch named "feature-login"
git branch # List all local branches (your active branch is highlighted)
git checkout feature-login # Switch over to your new branch
git checkout -b feature-login # Shortcut: Creates the branch AND switches to it instantly
git branch -m old-name new-name # Rename a branch

Once your feature is safely merged into the main project, you should delete the workspace to keep your repository clean.

git branch -d feature-login    # Safe Delete: Only deletes if the branch was successfully merged
git branch -D feature-login # Force Delete: Destroys the branch even if work is unmerged and lost

Branching Best Practices:

  • Keep names uniform: Use prefixes like feature/login-form, bugfix/crash-on-upload, or hotfix/security-patch.
  • One job per branch: Never build two completely unrelated features inside the same branch. Keep branches small and focused.
  • Stay updated: Regularly pull the latest changes from your team’s development branch into your working branch to minimize complex merge conflicts down the line.

12. Git Merge (Combining Timelines)

Merging is how you take the histories and features built on two separate branches and fuse them back together. Always switch to the receiving branch (the one you want to update) before running the merge command.

git checkout main
git merge <branch-name>
  • Fast-Forward Merge (Default): If the main branch hasn't received any new commits since you created your feature branch, Git won't create a bulky new "merge commit." It simply slides the main branch pointer forward to meet your feature's newest commit.
  • No Fast-Forward (--no-ff): Forces Git to create a dedicated merge commit, even if it could have done a fast-forward. This is excellent for teams who want a visible structural loop in their graph history showing exactly when a feature was integrated.
git merge --no-ff <branch-name>
  • Squash Merge (--squash): Condenses all 20 of your small, messy feature commits into one single, clean block of changes. Because it flattens history, Git does not automatically commit it—you must manually run the commit step right after to finish the job:
git merge --squash <branch-name> 
git commit -m "Squashed feature-login into a single commit"

If you and a teammate edit the exact same line of code in the same file, Git will pause the merge and flag a Merge Conflict. It will inject markers directly into your code file looking like this:

<<<<<<< HEAD
Your current code on the destination branch (e.g., main)
=======
The incoming code from the branch you are merging (e.g., feature-login)
>>>>>>> feature-login
  • To resolve it: Open the file, delete the structural markers (<<<<<<<, =======, >>>>>>>), manually edit the text to keep the correct lines of code, and then run:
git add .
git commit -m "Resolve merge conflict between main and feature-login"
  • To back out safely: If the conflict is too chaotic and you want to abort the attempt entirely to go back to how things were before you typed the merge command, run:
git merge --abort

Best Practices for Merging Branches:

  • Always commit or stash your changes before starting a merge.
  • Regularly merge from the main branch into your feature branch to minimize conflicts.
  • Read and resolve conflicts carefully — don’t just accept all changes blindly.
  • Write clear and descriptive merge commit messages.

13. Rebase (Rewriting History)

Rebasing is an alternative to merging. Instead of combining branches with a messy cross-over merge commit, rebasing takes your entire chain of feature commits, temporarily lifts them up, and re-plants them cleanly onto the very tip of the target branch. This results in a completely straight, linear, and clean project timeline.

git checkout feature-login
git rebase main # Plucks feature-login commits and appends them to the end of main

The Golden Rule of Rebasing: > Never rebase a public branch! Rebasing physically rewrites your history and changes your commit ID hashes. If you rebase commits that other developers have already pulled down to their own computers, you will scramble their Git histories and cause massive sync issues. Only rebase local branches that you haven’t shared with anyone else yet!

git rebase -i HEAD~4  # Interactive rebase for fixing last 4 commits

This launches a text editor displaying your 4 commits in chronological order from top to bottom, preceded by an action keyword (default is pick). By changing the word pick to a different command keyword, you instruct Git how to reshape history when you save and close the file:

  • pick: Keep the commit exactly as it is.
  • reword: Keep the commit's code changes, but stop the process to let you rewrite the commit message (perfect for fixing typos or expanding explanations).
  • edit: Pauses execution at this specific moment in history, allowing you to amend the code, split the commit into two separate commits, or add forgotten files.
  • squash: Fuses this commit into the commit directly above it and prompts you to merge their text descriptions together.
  • fixup: Fuses this commit into the commit directly above it but discards its log message. This is perfect for instantly hiding small bug fixes or minor code adjustments.
  • drop: Completely deletes the commit and all its code changes from the project timeline.

14. Git Cherry-pick (Precision Plucking)

Cherry-picking allows you to select a single, specific commit from an entirely separate branch and copy it over to your active branch, completely ignoring the rest of the historical timeline it belonged to.

When to use it

  • Hotfixes: A critical bug was fixed in a development sandbox branch, and you need to deploy only that specific fix directly to the production branch without launching the unapproved features around it.
  • Salvaging Work: A feature branch was abandoned, but it contained one stellar piece of logic you want to save and use in your current task.
git checkout main                # 1. Switch to the branch where you want to apply the change
git cherry-pick <commit-hash> # 2. Duplicate that specific commit onto your branch

15. Git Bisect (The Binary Search Debugger)

git bisect is a specialized debugging tool that uses a binary search algorithm to look backward through your project history and isolate the exact, specific commit that introduced a bug into your software.

Imagine you return to a project after two weeks. You run the app, and a feature is completely broken. It worked fine two weeks ago, but 200 commits have been made since then. Instead of manually testing dozens of commits one-by-one, Git Bisect narrows down the culprit in just a few strategic steps.

git bisect start              # 1. Start the investigation wizard
git bisect bad # 2. Tell Git that the CURRENT active code has the bug
git bisect good 1a2b3c4d # 3. Tell Git a specific older commit hash where the code worked perfectly
git bisect reset # 4. Exit the wizard

Once you enter these parameters, Git automatically checks out a commit directly in the middle of that timeline. You run your application and test the feature:

  • If the bug is still there, type: git bisect bad
  • If the bug is gone, type: git bisect good

Git will continuously split the remaining commits in half based on your answers until it prints out the exact author, date, and commit ID that broke your code.

16. Git Reflog (The Emergency Safety Net)

The Reflog (Reference Log) is a silent internal logbook that records every movement of the HEAD pointer on your local system. It tracks actions that standard git log completely ignores—such as switching branches, pulling updates, undoing commits, or running rebases.

If you accidentally force-deleted an unmerged branch, ran a disastrous rebase that wiped out your afternoon’s progress, or ran a git reset --hard and lost your local work, the Reflog is where you go to save your project.

Because Git rarely deletes data immediately, your “lost” commits are still sitting silently floating in your system background for about 30–90 days before garbage collection clears them.

git reflog
git reset --hard 9f8e7d6 # Resurrects your lost files and timeline instantly

17. Git Worktrees (Multi-Tasking)

Git Worktrees allow you to have multiple branches checked out simultaneously into completely separate folders on your computer, all sharing the same underlying .git directory history.

# syntax: git worktree add <path-to-new-folder> <branch-name>
git worktree add ../hotfix-emergency main
# Clean up and remove the worktree once the fix is deployed
git worktree remove ../hotfix-emergency
  • Running that command creates a new directory right next to your current project folder containing a clean copy of your main branch code.
  • Open that new folder in a second instance of your code editor, write the hotfix, commit it, and push it straight to production.
  • Close that window, delete the directory when finished, and continue typing code inside your untouched feature-auth branch workspace.

5. The Repository Gatekeeper: .gitignore

It is a plain-text configuration file placed in the root directory of your project. Git reads this file line-by-line and completely ignores any paths, files, or extensions matching the specified rules. It only works on untracked files.

Common files to ignore:

  • Build output (.class, .pyc, *.o)
  • Log files (*.log)
  • Temporary files
  • IDE/editor files (.idea/, .vscode/)
  • OS files (.DS_Store, Thumbs.db)
  • Environment variables/credentials (.env)

Add .gitignore when creating a new repository on GitHub:

  1. Go to github.com → New repository
  2. Scroll to “Add .gitignore” dropdown
  3. Select your language/template (Python, Node, Java, etc.)
  4. Create repository

For existing repositories, use the web editor:

  1. Navigate to your repo on GitHub
  2. Click “Add file” → “Create new file”
  3. Name it .gitignore
  4. Add your patterns
  5. Commit to your branch

If a file is already tracked by Git, it will continue to be tracked even after adding it to .gitignore. So you must untrack it first:

git rm --cached FILENAME    # Remove from Git tracking only
git add .gitignore # Add the .gitignore file
git commit -m "Stop tracking FILENAME and add gitignore"
git push origin main

6. Performance & Maintenance

  • git gc (Garbage Collection): This utility cleans, compresses, and optimizes your local object database. It packs loose commits and files into tightly zipped data containers, updating references and improving local speed performance.
git gc --prune=now
  • git prune: A housecleaning utility that searches your repository for loose objects that are completely unlinked to any branch or reference pointer (such as commits left orphaned after a destructive rebase) and safely removes them from disk storage.
  • git filter-repo (Purging Large Assets from History): It permanently scrubs a file entirely out of your repository's historical memory as Git remembers everything, so it will keep 500mb file even if you deleted it from repository.
# Install it first via your package manager (e.g., sudo dnf install git-filter-repo)
git filter-repo --path pathway/to/large-file.zip --invert-paths

7. GitHub Secrets

GitHub Secrets are encrypted environment variables that you create in an organization, repository, or repository environment. They allow you to store sensitive data — such as API keys, SSH keys, passwords, and access tokens — so that your GitHub Actions CI/CD workflows can use them securely without exposing them in your plaintext source code.

To add a secret to a specific repository, follow these steps:

  • Navigate: Open your web browser, go to your repository on GitHub, and click on the Settings tab in the top navigation bar.
  • Locate Security: In the left-hand sidebar, scroll down to the Security section.
  • Open Actions Settings: Click on Secrets and variables, then select Actions from the dropdown options.
  • Create New Secret: Click the green New repository secret button in the top right.
  • Name: Input a clear, descriptive identifier (e.g., STRIPE_API_KEY). Always use uppercase letters and underscores, as this is the standard naming convention for environment variables.
  • Secret: Paste your raw token, private key, or password into the value box.
  • Save: Click Add secret to finalize the process.

--

--