> For the complete documentation index, see [llms.txt](https://furkhan324.gitbook.io/workspace/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://furkhan324.gitbook.io/workspace/dev/git/going-back-in-time.md).

# Going Back in Time

## Undoing things: Reset & Checkout

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

{% embed url="<https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting>" %}

### Going Back in Time

Here are common scenarios that fit in this category:&#x20;

* 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

{% code title="before-state" %}

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

{% endcode %}

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
```

{% code title="before-state" %}

```
             (C3) -> (C4) -> (C5)
            /                    ^ STK:1
(C1) -> (C2)
           ^ Master     
```

{% endcode %}

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'
```

{% code title="before-state" %}

```
             (C3) -> (C4) -> (C5)
            /                    ^ STK:1
(C1) -> (C2) < Master
            \
             (C6)
                ^ STK:2 
```

{% endcode %}

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.

{% code title="before-state" %}

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

{% endcode %}

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.

{% embed url="<https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified>" %}

#### 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.&#x20;

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>
```
