Arc 2 Quest 08

Rewriting History

Amend, rebase, reset and reflog

Introduction

You enter a secret wing of the Archives, hidden behind an ancient tapestry. The room is dimly lit by floating candles. Scratched-out, scraped, and rewritten scrolls pile up on the shelves. The Master Archivist closes the door behind you with a solemn gesture.

"Apprentice, you now master branches and the merging of chronicles. But there exists an older, more powerful - and more dangerous - art. Certain elite Archivists knew how to rewrite History itself - modify a past entry, reorganize the chronology, erase an event as if it had never happened. This art is useful, but it obeys one absolute golden rule: you never rewrite a chronicle that has already been shared with other guilds."

Modify the last commit - git commit --amend

You just recorded an entry in the archives, but you notice a mistake. No need to create a new entry - you can modify the last one:

Fix the last commit message

git commit --amend -m "New corrected message"

Add a forgotten file to the last commit

git add forgotten-file.txt
git commit --amend --no-edit

The --no-edit option keeps the original message. The commit is replaced by a new one (with a different hash).

When to use --amend?

  • You made a typo in the message
  • You forgot to add a file
  • You want to adjust the content of the last commit

--amend does not modify the existing commit - it replaces it. The old commit disappears from the visible history (but remains recoverable via git reflog).

Rebase - Rewriting the chronology

git rebase is one of the most powerful tools in Git. It allows you to replay your commits on a different base, as if you had started your work from a more recent point.

Principle

Imagine you are working on a feature branch created from main. In the meantime, other commits have been added to main. Rebase takes your commits and replays them one by one on top of main:

Before the rebase:

      C---D  (feature)
     /
A---B---E---F  (main)

After git rebase main (from feature):

              C'---D'  (feature)
             /
A---B---E---F  (main)

Commits C and D become C' and D' - these are new commits (new hashes) with the same content, but repositioned.

How to rebase

# Switch to the branch to rebase
git switch feature

# Rebase onto main
git rebase main

Your commits from feature are now on top of the latest commits from main. The history is linear and clean.

Rebase vs Merge - The great debate

Both allow you to integrate changes from one branch into another, but in very different ways.

Merge (fusion)

git switch main
git merge feature
      C---D  (feature)
     /     \
A---B---E---F---G  (main, merge commit)
  • Creates a merge commit
  • Preserves the history as it actually happened
  • The history can become complex with many branches

Rebase

git switch feature
git rebase main
              C'---D'  (feature)
             /
A---B---E---F  (main)
  • No merge commit - linear history
  • Rewrites the history (new hashes)
  • Easier to read

When to use which?

Situation Recommendation
Update your branch with the latest changes from mainRebase
Integrate a completed branch into mainMerge
Branch already shared (pushed)Merge (never rebase!)
Clean up history before sharingRebase

The Golden Rule

ABSOLUTE RULE: Never rebase commits that have been pushed to a shared repository.

Rebase rewrites history by creating new commits. If other people have based their work on the old commits, you create total chaos - duplicates, impossible conflicts, and very unhappy colleagues.

In summary:

  • Local commits only? Rebase as much as you want.
  • Already pushed? Do not touch - use merge.

Interactive rebase - A preview

Interactive rebase (git rebase -i) allows you to manipulate multiple commits at once: reorder, squash, edit, drop. It is an extremely powerful tool that we will not practice in this exercise, but you should know about:

git rebase -i HEAD~3

This command opens an editor with the last 3 commits and options like:

  • pick - keep the commit as is
  • reword - change the message
  • squash - merge with the previous commit
  • drop - delete the commit

It is the ultimate tool for cleaning up a history before sharing it.

Git Reset - Going back in time

git reset allows you to move HEAD (and potentially the branch) to a previous commit. There are three modes, increasingly destructive:

git reset --soft HEAD~1

git reset --soft HEAD~1
  • Undoes the last commit
  • Files remain in the staging area (ready to be re-committed)
  • Useful for: rephrasing a commit or changing its content

git reset --mixed HEAD~1 (default)

git reset HEAD~1
  • Undoes the last commit
  • Files return to the working directory (unstaged)
  • This is the default behavior (no need for --mixed)
  • Useful for: reworking modifications before re-committing them

git reset --hard HEAD~1

git reset --hard HEAD~1

WARNING - DANGER! This command is destructive and irreversible (except via reflog). It removes the commit AND all associated modifications. Modified files are permanently lost. Use it only if you are absolutely sure you want to erase everything.

Visual summary

Mode Commit Staging Files
--softUndonePreservedPreserved
--mixed (default)UndoneClearedPreserved
--hardUndoneClearedDeleted

Git Reflog - The safety net

Made a mistake? One too many reset --hard? Don't panic. Git keeps a secret record of all HEAD movements in the reflog:

git reflog

The reflog displays every action that modified HEAD: commits, rebase, reset, checkout... Even "deleted" commits appear there for at least 30 days.

Recovering a lost commit

# 1. Find the hash of the lost commit in the reflog
git reflog

# 2. Return to that commit
git reset --hard <hash-of-lost-commit>

The reflog is your ultimate safety net. As long as a commit has existed, you can find it again.

Before any risky operation (rebase, reset --hard), note the hash of the current commit with git log --oneline -1. In case of trouble, you can always go back to it.

Practical exercise - Cleaning the chronicles

The Master Archivist entrusts you with a poorly maintained register. Entries contain errors, the chronology is confused. Your mission: restore order using --amend and rebase.

"These chronicles are a disaster. Mistakes in the entries, events in the wrong order... Clean it all up. Show me that you have mastered the art of rewriting History."

Step 1 - Create the register

Create a new folder and initialize a Git repository:

mkdir chroniques-nettoyees
cd chroniques-nettoyees
git init -b main

Step 2 - Record three entries (with an error)

Create a file registre.txt and make 3 commits:

echo "Day 1: Founding of the kingdom" > registre.txt
git add registre.txt
git commit -m "Add Day 1 entry"

echo "Day 2: Alliance with the elves" >> registre.txt
git add registre.txt
git commit -m "Add Day 2 entry"

echo "Day 3: Discovery of the gold mine" >> registre.txt
git add registre.txt
git commit -m "Addd Day 3 entry"

Oops! The message of the last commit contains a typo: "Addd" instead of "Add".

Step 3 - Fix with --amend

Fix the last commit message:

git commit --amend -m "Add Day 3 entry"

Verify with git log --oneline that the message is corrected.

Step 4 - Create a parallel branch

Create a refonte-archives branch and add entries to it:

git switch -c refonte-archives

echo "Day 4: Construction of the fortress" >> registre.txt
git add registre.txt
git commit -m "Add Day 4 entry"

echo "Day 5: Peace treaty with the dwarves" >> registre.txt
git add registre.txt
git commit -m "Add Day 5 entry"

Step 5 - Add a commit on main

Return to main and add a commit:

git switch main

echo "Appendix: List of kings" >> annexes.txt
git add annexes.txt
git commit -m "Add the list of kings as appendix"

Step 6 - Rebase the branch

Rebase refonte-archives onto main to get a linear history:

git switch refonte-archives
git rebase main

Step 7 - Verify the result

Admire the clean, linear history:

git log --oneline --graph --all

You should see all commits aligned on a single line, with no forks or merge commits.

Step 8 - Run the verification

Run the verification script to validate your quest:

Bash (Linux / macOS / Git Bash on Windows):

bash verifier.sh

PowerShell (Windows):

.\verifier.ps1

The script checks:

  1. You are in a Git repository
  2. You have used --amend (visible in the reflog)
  3. You have performed a rebase (visible in the reflog)
  4. At least 3 commits exist in the history

The Master Archivist examines the rewritten chronicles, running his finger along the carefully reorganized lines.

"Impressive, Apprentice. The history is clean, linear, readable. You corrected the errors without leaving traces, and reorganized the chronology with elegance. But never forget the golden rule: you only rewrite what has not yet been shared. Breaking this rule means sowing chaos across all guilds."