12  Rewinding work

12.1 Prep exercise.

Log into the server: https://edupod.cns.utexas.edu/ and choose Rstudio. Then your task is to create a git repository that when you run our long viz command

git log --oneline --abbrev-commit --all --graph --decorate --color

Your screen shows this result:

test-rewind % git log --oneline --abbrev-commit --all --graph --decorate --color                         
* 50590c5 (HEAD -> main) made third edit
* 39f89db made second edit
* 1b2162e made first edit

Hint: You will need to start by making a directory called test-rewind.

12.2 Why rewind?

When we are working we often want to try things out before we are 100% sure that they will work. We want to be able to experiment and find our way through a problem. If our experiment doesn’t work, we want to be able to step backwards in time, to find an earlier version that is a good new starting point.

In many ways this is identical to the idea of a “save point” in a game. We can step backwards in time and try again. We can reload that point at any time in the future. In our paper plane analogy, we can reach out and grab any tray in our repository.

Git enables us to save full copies of our working directory. We can then get back to the state of our work at any time we made a commit. When we check out a historical state, we get the files and the folders as as they were. So git actually swaps out the directory.

When I first started using git, I found this a bit confusing. usually when one restores from a backup, it is more like downloading a file. One gets to choose: - what to call the newly obtained older version - where to put it - what to do if there is a file that would be over-written.

What git does, though, is it swaps out all the files and folders with the previous version.

As we’ve seen, though, git is more fine-grained than a video game save-point. We often have files that have changed that we don’t want included in our save-point, this is why we have the git add stage before git commit.

Thus we can have untracked files or folders hanging around in our working folder. Git won’t change these when we do a checkout. So what happens is:

  1. git checks that all tracked files are in a “clean” state. This means that they are unchanged from the last commit. This is git checking that you have “saved your work” before it swaps out the files.
  2. git goes to its repository, locates the commit you ask for, and swaps all the tracked files and folders in the working directory.
  3. git remembers what commit you’ve moved to, so that if you make edits you can decide how they should be applied into the stream of commits in your repository.

To move backwards in time we use the git checkout command. We have to let git know which commit we want to go back to. We can specify that using the name that git uses, which is the hash (e.g., 1b2162e) shown by git log.

Starting with our 3 commit test-rewind repo:

jlh5498@INFO-A64206 test-rewind % git log --oneline --abbrev-commit --all --graph --decorate --color
* 50590c5 (HEAD -> main) made third edit
* 39f89db made second edit
* 1b2162e made first edit

We can move to the first commit using

jlh5498@INFO-A64206 test-rewind % git checkout 1b2162e

which produces the output

Note: switching to '1b2162e'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 1b2162e made first edit

If we run our viz command we can see a little more:

jlh5498@INFO-A64206 test-rewind % git log --oneline --abbrev-commit --all --graph --decorate --color
* 50590c5 (main) made third edit
* 39f89db made second edit
* 1b2162e (HEAD) made first edit

See how the word HEAD now appears on the bottom line and not the top line? This is git’s way of telling us what is checked out.

When git says detached HEAD (a little intense sounding) git is highlight for us that our current working directory is not at the last commit. This means that if we try to make a new commit git wants us to know that it won’t just pop onto the top of the repo like usual. (git will create an unnamed branch, we’ll discuss branches later).

For now, though, we can inspect files back at this version, and we can shift to another version (using checkout). For example we can move back to our top commit, using git checkout main (where main might be master on a system configured with an older git).

jlh5498@INFO-A64206 test-rewind % git checkout main
jlh5498@INFO-A64206 test-rewind % git log --oneline --abbrev-commit --all --graph --decorate --color
* 50590c5 (HEAD -> main) made third edit
* 39f89db made second edit
* 1b2162e made first edit

Notice how HEAD now points to the top commit? If we edit/add/commit our commits will drop back on top.

jlh5498@INFO-A64206 test-rewind % git add README 
jlh5498@INFO-A64206 test-rewind % git commit -m "Made fourth edit"
[main ff7997b] Made fourth edit
 1 file changed, 1 insertion(+)
jlh5498@INFO-A64206 test-rewind % git log --oneline --abbrev-commit --all --graph --decorate --color
* ff7997b (HEAD -> main) Made fourth edit
* 50590c5 made third edit
* 39f89db made second edit
* 1b2162e made first edit

Remember, git swaps out all the tracked files when you do a checkout. If you have untracked files you will find they are unaffected by a git checkout. Create a file called my-untracked-file run git status then run git checkout <earlier-commit> (where <earlier-commit> is a hash for your first commit), then run git status again.

12.3 Revert - commits to undo commits

See https://github.blog/2015-06-08-how-to-undo-almost-anything-with-git/