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
(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
(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'
(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.
(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
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?