Hands-on Git Exercises: Practical Tasks and Challenges

Learn Git by Doing: A Hands-on Approach

The best way to master Git is through deliberate practice. This guide contains 15 hands-on exercises ranging from basic commands to advanced recovery scenarios. Each exercise includes a clear objective, step-by-step instructions, hints, and a detailed solution. Create a practice repository and work through these exercises to build real Git fluency.

Getting Started: Create a practice directory and initialize a Git repository. All exercises can be done locally—no remote connection needed. Use mkdir git-practice && cd git-practice && git init to begin.

📊 Your Progress Tracker

0/15 exercises completed

🟢 Beginner 🟡 Intermediate 🔴 Advanced 🔵 Challenge
📝 Exercise 1: First Commit
🌿 Exercise 2: Branch Basics
🔀 Exercise 3: Merge Practice
⚡ Exercise 4: Rebase Workflow
💥 Exercise 5: Conflict Resolution
⏪ Exercise 6: Undo Changes
🆘 Exercise 7: Reflog Recovery
🔍 Exercise 8: Bisect Debug
📦 Exercise 9: Stash Management
🏷️ Exercise 10: Tagging Releases
🔄 Exercise 11: Interactive Rebase
🔐 Exercise 12: Signed Commits
🧹 Exercise 13: Clean History
🚑 Exercise 14: Hotfix Simulation
🎯 Exercise 15: Recovery Challenge
Exercise 1
Your First Commit Beginner
🎯 Objective: Create your first Git repository, add files, and make your initial commit. Understand the basic Git workflow.
📝 Tasks:
  1. Create a new directory called git-exercise-1 and initialize a Git repository
  2. Create a file called README.md with the content "# My Git Practice"
  3. Create a second file called hello.txt with the content "Hello, Git!"
  4. Check the status of your repository
  5. Stage both files for commit
  6. Commit the files with the message "Initial commit: add README and hello.txt"
  7. View the commit history
💡 Hint: Use git status frequently to see what's happening. Remember that git add stages files, and git commit -m "message" creates the commit.
Exercise 2
Branching Basics Beginner
🎯 Objective: Learn to create, switch between, and delete branches. Understand that branches are lightweight pointers.
📝 Tasks:
  1. From your repository in Exercise 1, create a new branch called feature/update-files
  2. Switch to the new branch
  3. Append "This is a new line" to hello.txt
  4. Create a new file notes.txt with any content
  5. Commit these changes with message "Update files on feature branch"
  6. Switch back to the main branch and verify that the changes are not visible
  7. List all branches and identify which one is active
  8. Delete the feature branch (after noting you can't delete the current branch)
💡 Hint: Use git branch to list branches, git checkout -b to create and switch, or git switch -c for the newer syntax. The -d flag deletes a branch.
Exercise 3
Merge Practice Beginner
🎯 Objective: Practice merging branches and understand fast-forward vs. non-fast-forward merges.
📝 Tasks:
  1. Create a new branch feature/add-content from main
  2. On the feature branch, create a file content.txt with three lines of text
  3. Commit this change
  4. Switch back to main and create a different file main-content.txt with some text
  5. Commit this change on main
  6. Now merge the feature branch into main
  7. Observe that this creates a merge commit (non-fast-forward)
  8. View the commit graph with git log --graph
💡 Hint: Because both branches have new commits, Git cannot fast-forward. It will create a merge commit. Use git log --graph --oneline to see the branch structure.
Exercise 4
Rebase Workflow Intermediate
🎯 Objective: Understand rebasing by replaying commits on top of another branch to create linear history.
📝 Tasks:
  1. Create a new branch feature/rebase-practice from main
  2. On this branch, create two commits: add file feature1.txt and then feature2.txt
  3. Switch to main and add a commit (create main-update.txt)
  4. Instead of merging, rebase the feature branch onto main
  5. Observe how the commit history becomes linear
  6. Compare the commit hashes before and after rebase
💡 Hint: While on the feature branch, run git rebase main. Git will temporarily remove your feature commits, apply main's new commits, then reapply your feature commits on top.
Exercise 5
Conflict Resolution Intermediate
🎯 Objective: Create and resolve a merge conflict. Learn to identify conflict markers and choose the correct resolution.
📝 Tasks:
  1. Create a file conflict.txt on main with content "Main line 1\nMain line 2" and commit it
  2. Create and switch to a branch feature/conflict
  3. On the feature branch, modify conflict.txt to change line 2 to "Feature line 2" and commit
  4. Switch back to main and modify the SAME line 2 to "Main updated line 2" and commit
  5. Attempt to merge the feature branch into main—observe the conflict
  6. Resolve the conflict by keeping both versions or choosing one
  7. Complete the merge and verify the result
💡 Hint: After merge conflict, open conflict.txt and look for <<<<<<<, =======, and >>>>>>> markers. Edit to resolve, then git add and git commit.
Exercise 6
Undoing Changes Intermediate
🎯 Objective: Practice various undo operations: unstage files, amend commits, revert commits, and reset commits.
📝 Tasks:
  1. Create a file mistake.txt and stage it with git add
  2. Unstage the file without discarding changes
  3. Create a commit with a typo in the message (e.g., "Inital commit")
  4. Amend the commit to fix the message
  5. Create three commits: A, B, C in sequence
  6. Use git revert to undo commit B (the middle one)
  7. Use git reset to go back to commit A (discard C and the revert)
  8. Use git reflog to find and return to your original state
💡 Hint: Remember: git reset has three modes: --soft (keep changes staged), --mixed (keep changes unstaged), --hard (discard changes). Use reflog as your safety net.
Exercise 7
Reflog Recovery Intermediate
🎯 Objective: Learn to use reflog to recover "lost" commits after destructive operations.
📝 Tasks:
  1. Create three commits: Commit1, Commit2, Commit3
  2. Use git reset --hard HEAD~2 to "lose" the last two commits
  3. Verify the commits are gone from git log
  4. Use git reflog to find the lost commits
  5. Recover Commit3 by resetting to its hash
  6. Create a branch at Commit2 to preserve it
💡 Hint: Reflog shows every movement of HEAD. Look for the "commit:" entries before your reset. The hashes are still valid even though they're not in the log.
Exercise 8
Git Bisect Debugging Advanced
🎯 Objective: Use git bisect to perform a binary search and find which commit introduced a "bug".
📝 Tasks:
  1. Create 10 commits, each adding a line to numbers.txt with a number from 1 to 10
  2. In commit 5, introduce a "bug" by writing "BUG" instead of "5"
  3. Now, pretending you don't know where the bug is, use git bisect to find it
  4. Mark the last commit as bad (contains bug) and first commit as good (clean)
  5. At each bisect step, check if the file contains "BUG"
  6. Continue until bisect identifies the exact commit
💡 Hint: Use git bisect start, then git bisect bad and git bisect good. Git will checkout middle commits. Test each, mark good/bad until the culprit is found.
Exercise 9
Stash Management Intermediate
🎯 Objective: Master git stash for temporarily saving work-in-progress changes.
📝 Tasks:
  1. On your main branch, create a file work-in-progress.txt with some content but DO NOT commit it
  2. You need to switch branches urgently, so stash your changes
  3. Verify the working directory is clean
  4. Create and switch to a new branch urgent-fix, make a commit, and switch back
  5. Apply your stash back
  6. Create another stash with a custom message
  7. List all stashes and apply a specific one
  8. Create a branch from a stash
💡 Hint: Use git stash push -m "message" for named stashes. git stash list shows all. git stash apply stash@{1} applies a specific stash. git stash branch creates a branch from a stash.
Exercise 10
Tagging Releases Intermediate
🎯 Objective: Practice creating and managing both lightweight and annotated tags for releases.
📝 Tasks:
  1. Create three commits representing versions: v1.0, v1.1, and v1.2
  2. Create a lightweight tag called v1.0 on the first commit
  3. Create an annotated tag v1.1 with message "Release version 1.1"
  4. Create a signed tag v1.2 (if GPG configured)
  5. List all tags
  6. Show details of the annotated tag
  7. Checkout a tag (observe detached HEAD)
  8. Push tags to a remote (simulate by adding a local remote)
  9. Delete a tag locally
💡 Hint: Use git tag v1.0 (lightweight), git tag -a v1.1 -m "message" (annotated), git tag -s v1.2 -m "message" (signed). git show v1.1 shows tag details.
Exercise 11
Interactive Rebase Advanced
🎯 Objective: Master interactive rebase to squash, reword, edit, and reorder commits.
📝 Tasks:
  1. Create 5 commits with messages: "WIP 1", "Add feature", "Fix typo", "Add tests", "WIP 2"
  2. Use interactive rebase to squash "Fix typo" into "Add feature"
  3. Reword "Add feature" to "feat: implement login feature"
  4. Reorder commits to put "Add tests" before the feature commits
  5. Delete the "WIP 2" commit entirely
  6. Verify the final history is clean and logical
💡 Hint: Run git rebase -i HEAD~5. In the editor, change 'pick' to 'reword', 'squash', or reorder lines. Save and exit to apply.
Exercise 12
Signed Commits Advanced
🎯 Objective: Configure and create signed commits using GPG to verify authorship.
📝 Tasks:
  1. Generate a GPG key pair (if you don't have one)
  2. Configure Git to use your GPG key for signing
  3. Create a signed commit
  4. View the commit signature in the log
  5. Create a signed tag
  6. Configure Git to sign all commits automatically
💡 Hint: Use gpg --full-generate-key to create a key. Find your key ID with gpg --list-secret-keys. Configure with git config --global user.signingkey [key-id]. Sign commits with -S flag.
Exercise 13
Cleaning History Advanced
🎯 Objective: Use git filter-repo to remove sensitive files or large files from repository history.
📝 Tasks:
  1. Create a repository with several commits, including one that accidentally added a file secret.txt containing "password=12345"
  2. Add more commits after the secret was added
  3. Use git filter-repo to completely remove secret.txt from all history
  4. Verify the file is gone from all commits
  5. Note that commit hashes have changed
💡 Hint: Install git-filter-repo with pip install git-filter-repo. Then run git filter-repo --path secret.txt --invert-paths to remove the file from all commits.
Exercise 14
Hotfix Simulation Advanced
🎯 Objective: Simulate a production hotfix scenario: create a hotfix branch, apply fix, deploy, and ensure fix is merged to all branches.
📝 Tasks:
  1. Create a repository with a main branch (production) and a develop branch
  2. Add a release tag v1.0.0 on main
  3. On develop, add several new features (simulate with commits)
  4. Simulate a critical bug found in production (in v1.0.0)
  5. Create a hotfix branch from the v1.0.0 tag
  6. Apply the fix and commit with message "hotfix: critical security patch"
  7. Merge hotfix to main and tag as v1.0.1
  8. Also merge hotfix to develop
  9. Verify that develop still has its features AND the hotfix
💡 Hint: The critical step is merging the hotfix to develop. If you skip this, the bug will reappear in the next release from develop.
Exercise 15
Ultimate Recovery Challenge Challenge
🎯 Objective: Combine multiple recovery techniques to rescue a seemingly lost repository state.
📝 Challenge Description:

You've been given a repository that has suffered multiple disasters:

  1. A developer ran git reset --hard HEAD~5 and lost 5 commits
  2. Another developer deleted a branch that contained important work
  3. Someone accidentally ran git gc and pruned some objects
  4. There's a dangling commit that contains a file with the word "RECOVER-ME"

Your task: Find and recover all lost work. Document each step and the final state.

💡 Hint: You'll need: reflog to find lost commits, fsck to find dangling objects, git log -g to search reflog messages, and git branch to restore branches. Work systematically.

🎉 Congratulations! You've completed all 15 hands-on exercises. You've practiced basic workflows, branching strategies, conflict resolution, recovery techniques, and advanced operations. These skills translate directly to real-world Git usage.

Next Steps: Create your own practice scenarios. Intentionally break repositories and practice recovery. The more you practice, the more confident you'll become.

After completing Exercise 14 (Hotfix Simulation), why is it critical to merge the hotfix into the develop branch as well as main?
  • To ensure the bug fix is included in future releases from develop
  • Because Git requires merging to all branches
  • To create more commits for the release notes
  • To test the fix in both branches

Exercise FAQ

How should I practice these exercises effectively?

Effective practice strategy:

  1. Create a dedicated practice directory: Keep practice repos separate from real work.
  2. Start with a clean slate: Run rm -rf .git and git init to reset between exercises if needed.
  3. Don't peek at solutions immediately: Try each exercise for at least 10-15 minutes before checking the solution.
  4. Experiment beyond the tasks: After completing an exercise, try variations—what happens if you do X instead of Y?
  5. Use git status frequently: After every command, see what changed.
  6. Document your learning: Keep a journal of commands you learned and scenarios you practiced.
  7. Repeat exercises after a week: Spaced repetition builds long-term memory.
What if I make a mistake during an exercise?

Making mistakes is part of learning! Here's how to handle them:

  • Use git reflog: Most mistakes can be undone by finding the pre-mistake state in reflog and resetting.
  • Start over: For practice repos, it's often fastest to delete the .git folder and re-initialize.
  • Learn from the mistake: Understand what went wrong—it's often more valuable than getting it right the first time.
  • Use git status and git log: These commands help you understand your current state.
  • When truly stuck: Check the solution, but then try to reproduce the exercise from memory.
How do these exercises translate to real-world scenarios?

Each exercise maps to common real-world situations:

  • Exercises 1-3: Daily development work—creating commits, branches, merges
  • Exercise 4-5: Keeping feature branches updated, handling team conflicts
  • Exercise 6: Fixing mistakes—every developer needs this
  • Exercise 7-8: Debugging and recovery—essential for senior roles
  • Exercise 9: Context switching—happens multiple times daily
  • Exercise 10: Release management—crucial for DevOps
  • Exercise 11: History cleanup before PRs—professional workflow
  • Exercise 12: Security compliance—enterprise requirements
  • Exercise 13: Incident response—handling security breaches
  • Exercise 14: Production hotfixes—real emergency situations
  • Exercise 15: Disaster recovery—worst-case scenarios
Previous: Git Interview Answers Next: Advanced Rebase