czay.dev
Writing

Git Fundamentals: An Introduction to Version Control and Practical Usage

A beginner's guide to version control with Git: what it is, why we use it, core commands, real-world analogies, common mistakes, practical tips, and a quick reference for daily workflow.

Furkan ÖzayJune 25, 2025 · 13 min read

1. Introduction and Motivation

When writing code or working on a project, tracking changes and reverting to a previous version when necessary is crucial. That's where Git comes in!

Explanation: Real-World Analogy

Git is like saving backups of a Word document with "Save As" at every step. But much smarter and automated!

✦

2. What Is Git and Why Do We Use It?

Explanation: Why Git?

Git is a version control system that records the history of your files and code step by step. This allows you to safely manage both your own changes and your teammates' contributions.

  • Undo: Made a mistake in your changes? With Git, you can easily restore previous states.
  • Teamwork: Multiple people can work on the same project without stepping on each other's toes.
  • Experimentation and confidence: You can try out a new feature without breaking the main codebase.
✦

3. Git Installation and Initial Setup

  • Download Git and install it for your operating system.
  • After installation, verify it by running git --version in your terminal.
  • Set your username and email:
    Bash
    git config --global user.name "Adınız Soyadınız"
    git config --global user.email "[email protected]"
✦

4. Core Concepts: Commit, Branch, Staging, HEAD, DAG

Explanation: How Does Git Work?

Git takes a "snapshot" of your files with every change. These snapshots are called commits and are linked together like a chain. This chain forms your project's history.

  • Staging Area (Index): The area where you prepare your changes before committing them.
  • Commit: A record of your project's state at a given moment.
  • Branch: Allows you to open different paths of development. The main branch is usually main or master.
  • HEAD: Points to the branch you are currently working on.
  • DAG (Directed Acyclic Graph): Commits are linked together in a directed, acyclic graph structure.

Explanation: Real-World Analogy

The staging area is like your shopping cart. Whatever you put in the cart gets committed; what you leave out stays on the shelf.

✦

5. Basic Git Commands: First Steps

Creating a New Git Repository

Bash
git init

Converts your current folder into a Git project.

Tracking Changes

Bash
git status

Shows modified files in your working directory and staged files.

Adding Files (Staging)

Bash
git add dosya.txt

Adds a specific file. For all files:

Bash
git add .

Saving Changes (Commit)

Bash
git commit -m "Açıklama yazın"

Permanently records your changes.

Viewing History

Bash
git log

Lists the complete commit history.

✦

6. Branches and Branching Strategies

  • Main Branch (main/master): Always production-ready, stable code.
  • Feature Branch: Created for new features and merged into the main branch once complete.
  • Hotfix/Release Branch: Used for urgent bug fixes or release preparation.

Explanation: Why Use Branches?

To develop multiple features or fixes simultaneously without interfering with one another.

  • Git Flow: Uses main, develop, feature, release, and hotfix branches for complex projects.
  • GitHub Flow: A simple workflow based around the main branch and short-lived feature branches.
✦

7. Working with Remote Repositories and GitHub

  • Remote Repo (Remote): A copy hosted on platforms like GitHub or GitLab.
  • Adding a remote repository:
    Bash
    git remote add origin <repo-adresi>
    git push -u origin main
  • Fetching the latest changes from a remote repository:
    Bash
    git pull
  • Cloning an existing project to your computer:
    Bash
    git clone <repo-adresi>
✦

8. Other Frequently Used Commands

  • git branch: Lists existing branches.
  • git checkout -b yeni-ozellik: Creates a new branch and switches to it.
  • git merge <dal>: Merges the specified branch into the current branch.
✦

9. Merge vs Rebase, Conflicts, and Resolutions

How Does a Merge Conflict Happen? (Scenario and Example)

Scenario: Two people make different changes to the exact same line of a file.

  1. A file exists on the main branch:
    txt
    mesaj.txt:
    Merhaba dünya!
  2. On the feature-a branch, this line is modified:
    txt
    mesaj.txt:
    Merhaba Copilot!
  3. On the feature-b branch, the same line is modified differently:
    txt
    mesaj.txt:
    Merhaba insan!
  4. First, feature-a is merged into the main branch. Then, an attempt is made to merge feature-b into main. Since there are two conflicting changes on the same line, Git raises a merge conflict.

Explanation: Real-World Analogy

If two people edit the exact same sentence in a Word document differently, someone has to decide which version is correct. Git asks you to make that decision.

✦

Merge/Rebase Commands and Resolving Conflicts

Merge

Bash
git merge feature-branch

Merges two branches together. Preserves the full commit history.

Rebase

Bash
git rebase main

Moves your branch to the tip of the main branch, providing a cleaner linear history.

Merge/Rebase Conflicts

  • When a conflict occurs, <<<<<<<, =======, and >>>>>>> markers appear in the file.
  • Resolve the conflicting lines manually, then run:
    Bash
    git add <dosya>
    git commit
  • You cannot complete a commit until conflicts are resolved.

Warning: Common Mistake

Running git add . and git commit without resolving the conflict markers can push broken code to the main branch.

✦

10. Common Mistakes and How to Recover (In Detail)

1. Committing on the Wrong Branch

Scenario: You thought you were working on a feature branch, but you committed directly on main (or vice versa).

Solution:

  1. Find the hash of the commit:
    Bash
    git log --oneline
  2. Switch to the target branch:
    Bash
    git checkout main
  3. Apply the commit to the main branch:
    Bash
    git cherry-pick <commit-hash>
  4. Remove the commit from the wrong branch:
    Bash
    git checkout feature
    git reset --hard HEAD~1

Tip: Pro Tip

With git cherry-pick, you can pick any specific commit and apply it to another branch.

✦

2. Accidentally Deleted a Commit

Scenario: A commit was lost during a git reset --hard or rebase operation.

Solution:

  1. Find the commit hash:
    Bash
    git reflog
  2. Recover the lost commit into a new branch:
    Bash
    git checkout -b kurtarma <commit-hash>

Tip: Debugging Tip

git reflog records almost every action you perform in your local repository. Don't panic—most lost commits can be recovered!

✦

3. Missing Commit After Merge or Rebase

Scenario: Some commits disappeared after a merge or rebase.

Solution:

  1. Find the commit hash using git reflog.
  2. Recover the commit by creating a new branch:
    Bash
    git branch kayip-commit <commit-hash>
  3. If needed, merge or cherry-pick it back into your target branch.
✦

4. Accidentally Deleted a File

Scenario: You deleted a file and want to restore it before committing.

Solution:

  • To restore it to its state in the last commit:
    Bash
    git checkout HEAD -- dosya.txt
  • To restore it from an older commit:
    Bash
    git checkout <commit-hash> -- dosya.txt
✦

5. Unable to Resolve a Merge Conflict

Scenario: You accidentally deleted conflict markers (<<<<<<<, =======, >>>>>>>) and corrupted the file.

Solution:

  • To reset the file and resolve the conflict from scratch:
    Bash
    git checkout --ours dosya.txt   # Keeps your changes
    git checkout --theirs dosya.txt # Keeps incoming changes
  • Then you can proceed with the merge process again.

Note: Motivation

Mistakes happen all the time in Git. The key is not to panic and troubleshoot step by step. Make git status, git log, and git reflog your best friends!

✦

Common Mistakes and Recovery Methods (Summary Table)

MistakeRecovery Method
Committed on the wrong branchgit cherry-pick, git reset
Deleted a commitgit reflog, new branch
Missing commit after merge/rebasegit reflog, git branch
Accidentally deleted a filegit checkout
Cannot resolve merge conflictgit checkout --ours/theirs
✦

11. Real-World Scenarios and Team Collaboration

  • Fork and PR: Forking someone else's project and submitting a pull request with your changes.
  • Upstream Sync: Fetching updates from the original repository to keep your fork up to date.
  • Code Review: Reviewing code changes through PRs before merging.

Tip: Pro Tip

When working in a team, develop every feature in a separate branch and merge it into the main branch via a PR.

✦

12. Advanced Topics

Squash

Scenario: You made 5 small commits on a feature branch, but you want to merge them into the main branch as a single commit.

Detailed Example:

  1. The feature/login branch has the following commits:
    • feat: kullanıcı adı inputu eklendi
    • fix: input typo düzeltildi
    • feat: şifre inputu eklendi
    • fix: şifre inputu typo düzeltildi
    • style: inputlara margin eklendi
  2. Before merging into main, you want to combine them into one commit:
    Bash
    git checkout feature/login
    git rebase -i HEAD~5
  3. In the interactive editor, set the first commit to pick and the remaining ones to squash. Edit the commit message and save.
  4. Result: All changes are combined into a single commit. Now you can merge into main.

Tip

Squashing keeps commit history clean and readable.

✦

Cherry-pick

Scenario: You want to pick a specific commit from another branch and apply it to your current branch.

Detailed Example:

  1. An urgent fix was committed on hotfix/bugfix:
    • fix: login bug düzeltildi (commit hash: a1b2c3d)
  2. You are working on feature/profile and want to apply this fix:
    Bash
    git checkout feature/profile
    git cherry-pick a1b2c3d
  3. Result: Only that specific commit is applied to your current branch. Your code is updated.

Tip

Extremely useful when you need to port an urgent fix across different branches.

✦

Revert

Scenario: You created an incorrect commit on the main branch, but you don't want to rewrite history.

Detailed Example:

  1. A file was mistakenly deleted on main:
    • commit hash: d4e5f6g
  2. To undo this commit:
    Bash
    git checkout main
    git revert d4e5f6g
  3. Result: The deleted file is restored, and a new revert commit is created.

Tip

Revert safely undoes faulty changes without altering existing history.

✦

Reset

Scenario: You made 3 unnecessary commits and want to remove them completely.

Detailed Example:

  1. Recent commits:
    • fix: typo
    • test: test kodu
    • debug: console.log eklendi
  2. To erase the last 3 commits:
    Bash
    git reset --hard HEAD~3
  3. Result: The repository reverts to the state 3 commits ago. Those commits and changes are completely discarded.

Warning

reset --hard is destructive and cannot be easily undone. Never use it on shared public branches!

✦

Reflog

Scenario: You accidentally deleted a branch or commit and want to recover it.

Detailed Example:

  1. A commit went missing after running git reset --hard.
  2. To locate the missing commit:
    Bash
    git reflog
    # Find the old commit hash in the output (e.g. 9z8y7x6)
    git checkout -b kurtarma 9z8y7x6
  3. Result: The lost commit is restored into a new branch.

Tip

Reflog logs almost every action you take in Git. Don't panic!

✦

Stash

Scenario: You need to switch branches urgently while working, but you don't want to commit unfinished work.

Detailed Example:

  1. You are on feature/search with uncommitted changes.
  2. You need to switch to the main branch:
    Bash
    git stash
    git checkout main
    # Once done, switch back to your feature branch
    git checkout feature/search
    git stash pop
  3. Result: Your changes are restored safely without losing any work.

Tip

Stash is ideal for switching branches without committing incomplete work.

✦

.gitignore and .gitattributes

Scenario: Your project contains files that should not be tracked, such as build output or secret keys.

Detailed Example:

  1. You have folders/files like node_modules/, .env, or dist/.
  2. Add them to your .gitignore file:
    txt
    node_modules/
    .env
    dist/
  3. Result: These files will be ignored by Git.
  4. Use .gitattributes for line ending configurations, for example:
    txt
    * text=auto

Tip

.gitignore prevents unneeded or sensitive files from entering your repository.

✦

Hooks

Scenario: You want to run automated tests before every commit.

Detailed Example:

  1. Open or create .git/hooks/pre-commit.
  2. Add the following script:
    Bash
    #!/bin/sh
    npm test
  3. Make the file executable:
    Bash
    chmod +x .git/hooks/pre-commit
  4. Result: Automated tests run before each commit; if tests fail, the commit is aborted.

Tip

Hooks help automatically enforce code quality in your repository.

✦

Submodules

Scenario: You want to include another Git repository (e.g., a shared library) as a submodule in your project.

Detailed Example:

  1. To add a shared library:
    Bash
    git submodule add https://github.com/ornek/ortak-kutuphane.git libs/ortak-kutuphane
  2. To update the submodule:
    Bash
    git submodule update --remote
  3. Result: The submodule is embedded in your project and kept up to date.

Tip

Submodules are ideal for sharing common code across multiple repositories.

✦

Shallow Clone & LFS

Scenario 1: A repository is very large, and you only want to download the latest snapshot quickly.

Detailed Example:

  1. To clone only the latest commit:
    Bash
    git clone --depth=1 https://github.com/ornek/buyuk-repo.git
  2. Result: Only the latest revision is downloaded instead of the entire history.

Scenario 2: Your repository contains large files (e.g., videos, datasets) that slow Git down.

Detailed Example:

  1. Set up Git LFS:
    Bash
    git lfs install
    git lfs track "*.mp4"
    git add .gitattributes
    git add video.mp4
    git commit -m "LFS ile video eklendi"
  2. Result: Large files are managed by LFS, keeping your main repository fast.

Tip

LFS improves performance in projects that handle large binary assets.

✦

13. FAQ and Resources

Frequently Asked Questions

Note: Advanced Questions About Git

Q: How can I keep my commit history clean? A: Using rebase and squash on feature branches, especially when working with a team, keeps history concise and readable.

Q: Merge or rebase? A: Use merge to preserve shared context on team branches, and rebase on feature branches to keep local history clean.

Q: Is it possible to completely erase a commit? A: You can edit history with git rebase -i or erase commits with git reset --hard. Use with caution!

Q: How do I manage large files? A: You can track large files using Git LFS.

Q: How do I update submodules? A: Use the git submodule update --remote command.

✦

Resources and Further Reading

Note

You are now ready to use Git not just at a basic level, but like a pro!