Going Back in Time

Use Git to go back in time

Undoing things: Reset & Checkout

Prereq: This article does a really good job explaining the difference between reset, checkout, & revert

Going Back in Time

Here are common scenarios that fit in this category:

  • Working on a new separate feature in parallel. In this case we need to start a branch from an older commit.

  • Reverting current feature branch to old commit because of breaking changes.

  • Looking at the repo at an earlier point in time and experimenting running code.

  • Resetting a file.

Feature in Parallel

Let's say we want to start a new feature from C2. Then simply checking out from that commit will not work because uncommitted changes will come along with you.

Git diagram keys: ! - UNTRACKED, * STAGED

before-state
             (C3) -> (C4) -> (!,*,...)
            /            ^ STK:1
(C1) -> (C2)
           ^ Master     

Instead, we want to commit/stash these changes first to get a clean index.

$ git add *; git commit -m 'C5'
OR
$ git add *;git stash
before-state
             (C3) -> (C4) -> (C5)
            /                    ^ STK:1
(C1) -> (C2)
           ^ Master     

Now, we can checkout a new feature from C2 in peace.

$ git checkout -b STK:2 C2
$ touch change.js
$ git add *; git commit -m 'C6'
before-state
             (C3) -> (C4) -> (C5)
            /                    ^ STK:1
(C1) -> (C2) < Master
            \
             (C6)
                ^ STK:2 

In the case that we had originally stashed our changes we can always repopulate our index/workdir by checking out STK:1 & then popping the stash.

$ git checkout STK:1
$ git stash pop

Broken Code

Okay let's assume we made changes that are breaking our code. I want to remove the uncommitted changes from the branch.

before-state
             (C3) -> (C4) -> (breaker.js!, breaker2.js*)
            /            ^ STK:1
(C1) -> (C2)
           ^ Master     

git reset --hard HEAD will bring us back to C4 but breaker.js will persist since it was never tracked. Reset only purges staged/tracked changes. So we have two choices

$ git add *; git reset --hard HEAD # Stage/track all changes & then reset stage/working dir to C4
OR
$ git clean -f; git reset --hard HEAD # Rm untracked chnages & then do the same as above
OR
$ git stash; git stash drop

Sources: https://stackoverflow.com/questions/9529078/how-do-i-use-git-reset-hard-head-to-revert-to-a-previous-commit

This is a very useful link to learn git resetting.

Experimenting

Say we wanted to test an earlier version of the app we are working on for nostalgia but we don't want to pollute our branch space. We simply checkout a commit leaving us on an unnamed branch.

$ git stash/git commit # Prep work to make sure our changes don't move with us
$ git checkout C3
$ npm start # Play around with an earlier version of the app

Fixing Specific Files

I was playing around with a stuff and I may have accidentally messed up a file. I still need to wrap up my work and commit the rest of what is still untouched. I can do two things here.

I can keep the local broken changes and commit the remainder of the staged changes by removing the changed file from stage.

$ git reset HEAD example.js
$ git commit -m 'Complete feature without example'
$ git add *; git stash
$ # run some tests & deploy feature
$ git stash pop # Time to go back to work on example.js

This workflow will remove the file from being committed initially. However, our working dir copy will still have the bad file.

What if we just wanted to fix stage & workdir back to how they used to be?

$ git checkout HEAD filename

Removing files after Commit

On occasion, you may realize that you may have committed a file you should not have. Now you want to make sure that it stays in your working directory while being marked for deletion on stage.

Simple run:

$ git rm --cached <file>

Last updated

Was this helpful?