Skip to content

Git Tag as a Fixed Refactoring Baseline: How to Get the Complete Diff at Any Time? ​

Schematic diagram of using a Git Tag to fix the refactoring baseline

In large-scale feature refactoring, we often encounter a pain point:The refactoring isn't finished yet, but I want to be able to see the complete changes "from the start of the refactoring until now" at any time., rather than by the various WIP commits in between,reset Disrupt the baseline, causing git diff Only fragmented increments can be seen.

This article documents a simple and reliable solution:use git tag Fixed reconstruction starting point.

Problem Background ​

git diff It is a relative comparison; its baseline determines what you see:

CommandComparison benchmarkWhat you see
git diffWorking Directory vs Staging AreaOnly unstaged increments
git diff HEADWorking directory vs last commitUncommitted changes; once committed, the baseline changes.
git diff <base>Working tree vs specified commitAll changes relative to base

During the refactoring process, if we:

  • First made a WIP commit to save progress.

  • again git reset --soft HEAD~1 Undo the commit and continue making changes

At this time git diff will become empty(Because the changes are all in the staging area), and you only want "the complete diff of the entire refactor," but no matter what you do, you just can't get it.

Root cause: The reference point has not been fixed.git diff The baseline drifts continuously with commit and reset.

Solution:git tag Fixed datum ​

Step 1: Create a tag before starting the refactoring ​

Ensure the workspace is clean, then create a tag on the current commit:

bash
git status              # Confirm the workspace is clean
git tag refactor-base   # Tag the current HEAD

💡 If there are already uncommitted changes in the workspace, it is recommended to clean them up before creating a tag; otherwise, the tag only marks the commit and does not include workspace changes.

Step 2: Refactor with confidence ​

Afterwards, regardless:

  • How many times to commit?

  • reset --soft/reset --mixed How many times

  • How many files were changed?

None of them affect the baseline.

Step 3: View the complete diff at any time ​

bash
git diff refactor-base > git.diff.all.txt

meaning:refactor-base That commit vs. the current working tree.

output: from the moment of the tag to now All changes, the intermediate process has no effect at all.

Step 4: Include untracked new files ​

git diff By default, untracked files are not shown (?? state). If you need to include:

bash
git add -A                                  # Add all to the staging area
git diff refactor-base > git.diff.all.txt

Or you just want to mark the intent but don't actually want to stage it:

bash
git add -N .
git diff refactor-base > git.diff.all.txt

Step 5: Clean up after refactoring is complete ​

bash
git tag -d refactor-base

Unexpected situation: What should you do if you forget to tag? ​

If you forgot to tag before starting the refactor, but Changes are still in the working directory/staging area, never committed, and there are remedies.

Option A: Use HEAD As the baseline (simplest) ​

As long as there has been at least one commit in the repository,HEAD It is inherently the "state before modification":

bash
git diff HEAD > git.diff.all.txt

git diff HEAD will output All uncommitted changes(working tree + staging area), equivalent to the complete diff "from the last commit to now".

If you're worried that the baseline will be lost after a later commit, just add a tag now:

bash
git tag refactor-base HEAD    # Baseline = the commit before you started making changes
git diff refactor-base         # Equivalent to git diff HEAD

Afterward, even if you commit ten times and reset five times,git diff refactor-base Still give it to you Complete changes from the refactoring starting point to now.

Option B: Commit the current changes first, then soft reset. ​

If you want to make the baseline clearer, you can first commit the current changes, and then use git reset --soft Restore:

bash
# 1. Commit all current changes (take a snapshot of the "refactoring starting point")
git add -A
git commit -m "base: snapshot before refactoring"

# 2. Create a tag to fix the baseline.
git tag refactor-base

# 3. Soft undo this commit, move the changes back to the staging area, and continue refactoring.
git reset --soft HEAD~1

⚠️ Note: at this time refactor-base points to the state after your changes, suitable for "tracking subsequent changes from now on," rather than "a complete diff including previous changes." To include previous changes, use Option A.

Case 3: Never committed before; the repository is brand new. ​

If this is a brand-new repository with not even a single commit, then There is no “before” to compare with.——All files are newly added.

bash
git add -A
git diff --cached              # View all contents in the staging area (relative to an empty repository)

It is recommended to make a commit first to lock in the current state; only then is there a baseline to discuss:

bash
git add -A
git commit -m "chore: initial snapshot"
git tag refactor-base

Summary ​

Your statusHow do you find the benchmark?Command
There have been commits, but the changes have not been committed.HEAD It is the benchmark.git diff HEAD
There have been commits, but I forgot which one is the starting point.git reflog Findgit tag refactor-base <commit>
Never committed; the repository already has history.Current HEADgit diff HEAD
Never committed, brand new repositoryNo baselineCommit once first

As long as there has been at least one commit in the repository,HEAD Natural is your benchmark,git diff HEAD you can get all uncommitted changes—no tag needed.

The value of tag lies in"across multiple commits can still lock onto the same baseline." If you haven't committed at all,HEAD That's enough.

Complete workflow example ​

bash
# 1. Fix the baseline before starting refactoring
git status
git tag refactor-base

# 2. During refactoring, change and commit freely.
git add -A && git commit -m "WIP: refactor part 1"
# ... Continue revising ...
git reset --soft HEAD~1
# ... Continue revising ...

# 3. View the full diff at any time.
git diff refactor-base > git.diff.all.txt

# 4. Refactoring complete
git add -A
git commit -m "feat: complete refactoring description"

# 5. Clean up benchmark markers
git tag -d refactor-base

Solution comparison ​

method基准ResultApplicable scenarios
git diffWorking directory vs staging areaOnly increments; the baseline drifts erratically.Daily small changes
git diff HEADWorking tree vs last commitAfter commit, the baseline changes.Single submission pre-check
git diff refactor-baseWorkspace vs fixed tagAlways complete✅Large-scale refactoring
git stash -uTemporary saveNeed git diff stash@{0}^ stash@{0}Brief absence
WIP commitSave progressBaseline becomes WIP commitNeed a save point

Common misconceptions ​

MisconceptionTruth
git diff View all changes by defaultWrong, only look at working directory vs staging area.
git reset --soft HEAD~1 after git diff Can see everythingWrong, the changes are in the staging area,git diff is empty, need to use git diff HEAD
After WIP commit git diff can see the entire refactoringWrong, the baseline has become a WIP commit, so only the incremental changes are visible.
git stash Include new files by defaultWrong, it needs to be added.-u only includes untracked files

Core conclusion ​

git diff It is a relative comparison, so a base must be fixed before refactoring begins.

use git tag refactor-base As an anchor, afterward no matter how many times you commit or reset,git diff refactor-base Always give you the "complete changes from the refactoring starting point to the present."

This solution is especially suitable for:

  • Large-scale feature refactoring: need to be able to submit the complete diff to AI (such as DeepSeek) at any time to generate a commit message.

  • Commit in stages, but want to keep track of the overall changes at any time.

  • Before code review, I want to see the complete changeset at once.

Tip: Give the tag a meaningful name ​

bash
git tag refactor/license-agent-v2
git diff refactor/license-agent-v2 > git.diff.all.txt

Or use a branch instead of a tag (same effect):

bash
git branch refactor-base
git diff refactor-base > git.diff.all.txt

Remember it in one sentence.: tag is an anchor for a fixed baseline; tag it once, and the diff will always be complete thereafter.

Last updated on11/07/2026, 02:16 PM
@fishfinal | @fishfinals | [email protected]