feat: add remotes and stash
This commit is contained in:
198
module-09-reset-vs-revert/README.md
Normal file
198
module-09-reset-vs-revert/README.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Module 10: Reset vs Revert
|
||||
|
||||
## Learning Objectives
|
||||
|
||||
By the end of this module, you will:
|
||||
- Understand the difference between `git reset` and `git revert`
|
||||
- Know when to use reset vs revert
|
||||
- Understand the three modes of reset (--soft, --mixed, --hard)
|
||||
- Safely undo commits in both local and shared branches
|
||||
- Understand the risks of rewriting history
|
||||
|
||||
## Challenge Description
|
||||
|
||||
You have two branches with problematic commits:
|
||||
1. **local-feature**: A private branch with bad commits that you haven't shared with anyone
|
||||
2. **shared-feature**: A branch that has been pushed and others might be using
|
||||
|
||||
Your task is to:
|
||||
1. Use `git reset` to remove the bad commit from the local-feature branch (safe because it's not shared)
|
||||
2. Use `git revert` to undo the bad commit from the shared-feature branch (safe because it preserves history)
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Git Reset: Rewriting History
|
||||
|
||||
`git reset` moves the branch pointer backward, effectively erasing commits from history. It has three modes:
|
||||
|
||||
**--soft**: Moves HEAD, keeps changes staged
|
||||
```bash
|
||||
git reset --soft HEAD~1
|
||||
# Commit is gone, but changes are staged and ready to commit again
|
||||
```
|
||||
|
||||
**--mixed** (default): Moves HEAD, keeps changes unstaged
|
||||
```bash
|
||||
git reset HEAD~1
|
||||
# Commit is gone, changes are in working directory but not staged
|
||||
```
|
||||
|
||||
**--hard**: Moves HEAD, discards all changes
|
||||
```bash
|
||||
git reset --hard HEAD~1
|
||||
# Commit is gone, changes are PERMANENTLY DELETED
|
||||
```
|
||||
|
||||
### Git Revert: Safe Undo
|
||||
|
||||
`git revert` creates a NEW commit that undoes the changes from a previous commit. History is preserved.
|
||||
|
||||
```bash
|
||||
git revert <commit-hash>
|
||||
# Creates a new commit that reverses the specified commit
|
||||
```
|
||||
|
||||
### Visual Comparison
|
||||
|
||||
**Before (both branches):**
|
||||
```
|
||||
A---B---C---D (D is the bad commit)
|
||||
```
|
||||
|
||||
**After Reset (rewrites history):**
|
||||
```
|
||||
A---B---C
|
||||
```
|
||||
Commit D is gone. If anyone else had D, they'll have problems.
|
||||
|
||||
**After Revert (preserves history):**
|
||||
```
|
||||
A---B---C---D---E
|
||||
```
|
||||
E is a new commit that undoes D. Everyone can pull E safely.
|
||||
|
||||
### When to Use Each
|
||||
|
||||
**Use Reset when:**
|
||||
- The commits haven't been pushed to a shared repository
|
||||
- You're cleaning up local commits before pushing
|
||||
- You made a mistake locally and want to start over
|
||||
- You're working alone on a branch
|
||||
|
||||
**Use Revert when:**
|
||||
- The commits have been pushed to a shared repository
|
||||
- Others might have based work on these commits
|
||||
- You want to preserve the complete history
|
||||
- You need a safe, reversible undo operation
|
||||
|
||||
### The Golden Rule
|
||||
|
||||
**Never use `git reset` on commits that have been pushed to a shared branch!**
|
||||
|
||||
This will cause problems for anyone who has pulled those commits. Use `git revert` instead.
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Reset (for local-only commits)
|
||||
git reset --soft HEAD~1 # Undo commit, keep changes staged
|
||||
git reset HEAD~1 # Undo commit, keep changes unstaged
|
||||
git reset --hard HEAD~1 # Undo commit, discard changes (DANGEROUS!)
|
||||
|
||||
# Reset to a specific commit
|
||||
git reset --hard <commit-hash>
|
||||
|
||||
# Revert (for shared commits)
|
||||
git revert <commit-hash>
|
||||
git revert HEAD # Revert the last commit
|
||||
|
||||
# See what would be affected before resetting
|
||||
git log --oneline
|
||||
git diff HEAD~1
|
||||
|
||||
# If you reset by mistake, you can sometimes recover with reflog
|
||||
git reflog
|
||||
git reset --hard <commit-hash-from-reflog>
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
Run the verification script to check your solution:
|
||||
|
||||
```bash
|
||||
.\verify.ps1
|
||||
```
|
||||
|
||||
The verification will check that:
|
||||
- local-feature branch has the bad commit removed via reset
|
||||
- shared-feature branch has the bad commit undone via revert
|
||||
- shared-feature has a revert commit in the history
|
||||
- All good commits are preserved
|
||||
|
||||
## Challenge Steps
|
||||
|
||||
1. Navigate to the challenge directory
|
||||
2. You're on the local-feature branch with a bad commit
|
||||
3. View commits: `git log --oneline`
|
||||
4. Use `git reset --hard HEAD~1` to remove the bad commit
|
||||
5. Switch to shared-feature: `git checkout shared-feature`
|
||||
6. View commits: `git log --oneline`
|
||||
7. Find the hash of the "Add broken feature" commit
|
||||
8. Use `git revert <commit-hash>` to undo it safely
|
||||
9. Run the verification script
|
||||
|
||||
## Tips
|
||||
|
||||
- `HEAD~1` means "one commit before HEAD"
|
||||
- `HEAD~2` means "two commits before HEAD"
|
||||
- Always check `git log` before and after reset/revert
|
||||
- `git reset --hard` is DANGEROUS - it permanently deletes uncommitted changes
|
||||
- If you're unsure, use `git reset --soft` instead of `--hard`
|
||||
- Revert will open an editor for the commit message - you can accept the default
|
||||
- You can always use `.\reset.ps1` to start over if you make a mistake
|
||||
|
||||
## Common Mistakes to Avoid
|
||||
|
||||
### Mistake 1: Using Reset on Pushed Commits
|
||||
```bash
|
||||
# DON'T DO THIS if the commit was pushed!
|
||||
git reset --hard HEAD~1
|
||||
git push --force # This will cause problems for others
|
||||
```
|
||||
|
||||
### Mistake 2: Using --hard Without Checking
|
||||
```bash
|
||||
# This DELETES your work permanently!
|
||||
git reset --hard HEAD~1 # Uncommitted changes are GONE
|
||||
```
|
||||
|
||||
### Mistake 3: Reverting the Wrong Commit
|
||||
```bash
|
||||
# Always double-check the commit hash
|
||||
git log --oneline
|
||||
git show <commit-hash> # Verify it's the right commit
|
||||
git revert <commit-hash> # Now revert it
|
||||
```
|
||||
|
||||
## Recovery from Mistakes
|
||||
|
||||
If you reset by accident, Git keeps a reflog:
|
||||
|
||||
```bash
|
||||
# See recent HEAD movements
|
||||
git reflog
|
||||
|
||||
# Find the commit you want to restore
|
||||
# Output looks like:
|
||||
# abc1234 HEAD@{0}: reset: moving to HEAD~1
|
||||
# def5678 HEAD@{1}: commit: The commit you just lost
|
||||
|
||||
# Restore it
|
||||
git reset --hard def5678
|
||||
```
|
||||
|
||||
The reflog is your safety net, but it only keeps history for about 30 days.
|
||||
|
||||
## What You'll Learn
|
||||
|
||||
Understanding when to use reset versus revert is crucial for safe Git usage. Reset is powerful but dangerous when used on shared commits, while revert is always safe but creates additional history. Mastering both commands and knowing which to use in different situations is a hallmark of Git expertise. The rule is simple: if in doubt, use revert - it's always safe.
|
||||
Reference in New Issue
Block a user