5  Interacting with your Git history

5.0.1 Restoring a previous version of a file

You can also use git checkout to recall a single file from a previous commit. In the terminal sequence below I use cat to show that the file in my work directory.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}

We can compare that to the file in the most recent commit in the develop branch using git show. They are the same file.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git show develop:fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}

Notice a call to git status reports the same thing without showing the files explicitly.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git status
On branch develop
nothing to commit, working tree clean

To retrieve a specific file from a prior commit you have to provide git checkout with identifying information for the commit and the file name. You can specify the appropriate commit with a absolute or relative reference. For an absolute reference provide the SHA #. For a relative reference the shorthand is HEAD~# where # is the number of commits prior to the latest commit. In the terminal sequence below I used checkout to retrieve a copy of fib_seq.R from 1 commit earlier (recall this commit had the less informative x and y axis labels).

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git checkout HEAD~1 fib_seq.R
Updated 1 path from abb8fba

Notice the earlier version of fib_seq.R is now present in my working directory (as shown in the output for cat), but was not included in the latest commit to my repository (as shown in the output to git show). Also note that `git status is aware of the change.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Number",
     ylab = "Ratio")
{golden_ratio <- fib_seq[51]/fib_seq[50]}
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git show develop:fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git status
On branch develop
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   fib_seq.R

If I wanted the earlier version of fib_seq.R to be associated with the most recent commit to my repository I would need to commit the file. In this case I did not want to change my repository so I used git checkout to go back the the most recent version (Using the relative reference HEAD to specify the latest commit). I often use this sequence to recall all or part of a code from a prior commit.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git checkout HEAD fib_seq.R
Updated 1 path from bd65128

This all worked, all call to cat shows that the file in my working directory has returned to the version with more informative file labels.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}

5.0.2 Retrieving a prior commit

Yet another use of git checkout is to recall a previous commit in its entirety. Since our repository only has one file, I created, staged, and committed a second file named test.R to demonstrate this functionality. In the terminal sequence below I show the contents of test.R and some now familiar content where I check the status of my repository and stage/commit the new file.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat test.R
#Blank file to see if we can use git checkout to retrieve an entire commit.
#Proof would be seeing this file and the correct version of fib_seq.R
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git status
On branch develop
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test.R

nothing added to commit but untracked files present (use "git add" to track)
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git add test.R
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git commit -m "Test.R file added. Used to test that git checkout recalls an entire commit" -m "added a second file so to verify both files come when I jump around commits."
[develop 4ef90af] Test.R file added. Used to test that git checkout recalls an entire commit
 1 file changed, 2 insertions(+)
 create mode 100644 test.R

To retrieve a prior commit you should create a new branch to house the past commit until you decide what to do with it. While not strictly necessary, creating a new branch is stable and protects your develop branch. In the terminal session below I use git checkout to create a new branch called old_state and fill it with the snapshot of the develop branch from 2 commits earlier. I am expecting old state to be missing test.R and have the less descriptive axis locations in the version of fib_seq.R.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git checkout -b old_state HEAD~2
Switched to a new branch 'old_state'

Two calls to cat confirm that my working directory does not contain test.R and has the older version of fib_seq.R

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (old_state)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Number",
     ylab = "Ratio")
{golden_ratio <- fib_seq[51]/fib_seq[50]}
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (old_state)
$ cat test.R
cat: test.R: No such file or directory
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (old_state)
$ git status
On branch old_state
nothing to commit, working tree clean

The next action depends on if you want the keep working on the prior commit. If you do you can modify files and stage/commit the result as appropriate prior to merging old_state back into develop. Since we purposely started the old_state feature branch from a prior version of develop the odds of a merge conflict are high. It does mean it’s a terrible idea but you should be doing this with intention. In the terminal session below I decided the prior commit was not an improvement on my original commit so I moved back to the develop branch and deleted the old_state branch. Two calls to cat proved that the original files were returned.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (old_state)
$ git checkout develop
Switched to branch 'develop'
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat test.R
#Blank file to see if we can use git checkout to retrieve an entire commit.
#Proof would be seeing this file and the correct version of fib_seq.R
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git branch -d old_state
Deleted branch old_state (was d0d260e).

5.0.3 Deleting/Reversing a commit

There are two ways to reverse a commit. The version you should choose depends on if you have pushed the commit to a remote repository.

5.0.3.1 Deleting a local commit

When the bad commit is local you can us git reset to delete the commit. The commit will disappear from your history. To demonstrate this command I modified the fib_seq.R by adding an inconsequential comment at the bottom of the file and used the cat command to show the file.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}

#Useless comment to demonstrate how to delete a commit

After adding and committing the file a call to git log shows that the commit was recorded.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git add fib_seq.R
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git commit -m "bad commit, plan to delete" -m "This commit has one change, a useless comment added to the fib_seq.R file. Plan to reset the HEAD to delete the commit"
[develop ae2fe59] bad commit, plan to delete
 1 file changed, 2 insertions(+)
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git log --oneline
ae2fe59 (HEAD -> develop) bad commit, plan to delete
4ef90af Test.R file added. Used to test that git checkout recalls an entire commit
ad2149a fixed merge conflict by accepting changes from label_plot branch
d0d260e Added labels to the golden ratio figure
a4c0f61 Added axis labels to golden ratio plot.
eb216a6 Merge branch 'cleanup' into develop
8b28369 remove maanual Fibonacci calculations
22dcfea (origin/main, main) Merge pull request #2 from carlyreimer/main
f811c50 Update fib_seq.R
edbaafa Update fib_seq.R
ac48c12 Finally added a for loop and golden ratio estimate
f732cdb Seventh Fibonacci number
9db5478 Sixth number in the Fibonacci seqence
5139049 Fifth entry in the Fibonacci sequence
0c92881 Fourth entry in the Fibonacci sequence
3bb6c98 Third entry in fib_seq
e17181f Initialize Fibonacci sequence

In the terminal session below I use git reset to reset my local repository to 1 commit prior to the most recent commit.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git reset HEAD~1 --hard
HEAD is now at 4ef90af Test.R file added. Used to test that git checkout recalls an entire commit

Notice that the comment I added to the most recent commit is no longer a part of the fib_seq.R file.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}

If we call git log again we will see that commit ae2fe59 has been removed for the repository. The important thing to note is git reset changes the repository history. If you are working locally this is OK but if you have already pushed the bad commit to a remote then deleting a part of your history will cause problems for collaborators who pulled the original history.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git log --oneline
4ef90af (HEAD -> develop) Test.R file added. Used to test that git checkout recalls an entire commit
ad2149a fixed merge conflict by accepting changes from label_plot branch
d0d260e Added labels to the golden ratio figure
a4c0f61 Added axis labels to golden ratio plot.
eb216a6 Merge branch 'cleanup' into develop
8b28369 remove maanual Fibonacci calculations
22dcfea (origin/main, main) Merge pull request #2 from carlyreimer/main
f811c50 Update fib_seq.R
edbaafa Update fib_seq.R
ac48c12 Finally added a for loop and golden ratio estimate
f732cdb Seventh Fibonacci number
9db5478 Sixth number in the Fibonacci seqence
5139049 Fifth entry in the Fibonacci sequence
0c92881 Fourth entry in the Fibonacci sequence
3bb6c98 Third entry in fib_seq
e17181f Initialize Fibonacci sequence
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git status
On branch develop
nothing to commit, working tree clean

5.0.3.2 Reversing a local/remote commit

Because revising your history in a public repository is bad collaboration Git has devised a solution. The git revert command can also be used to undo a mistaken commit but it does so in a very deliberate way… by creating a new commit that exactly undoes the prior commit. This method provides a stable Git history to your collaborators. In the git session below I modified the fib_seq.R again (with an inconsequential comment) and added/committed the change. git log shows the new commit.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ cat fib_seq.R
#Create a Fibonacci sequence to practice git operations
#Adam Reimer & Carly Reimer

fib_seq <- c(0, 1)
for (i in 3:51) fib_seq[i] <- sum(fib_seq[(i-1):(i-2)])

plot(1:50, fib_seq[2:51]/fib_seq[1:50],
     type = "l",
     xlab = "Fibonacci Number in Denominator",
     ylab = "Ratio Between Succesive Fibonacci Numbers")
{golden_ratio <- fib_seq[51]/fib_seq[50]}

#A second useless comment. Plan to commit then revert the commit.
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git status
On branch develop
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   fib_seq.R

no changes added to commit (use "git add" and/or "git commit -a")
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git add fib_seq.R
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git commit -m "bad commit, plan to revert" -m "This commit has one change, a useless comment added to the fib_seq.R file. Plan to revert the commit""
> "
[develop a0c849e] bad commit, plan to revert
 1 file changed, 2 insertions(+)
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git log --oneline
a0c849e (HEAD -> develop) bad commit, plan to revert
4ef90af Test.R file added. Used to test that git checkout recalls an entire commit
ad2149a fixed merge conflict by accepting changes from label_plot branch
d0d260e Added labels to the golden ratio figure
a4c0f61 Added axis labels to golden ratio plot.
eb216a6 Merge branch 'cleanup' into develop
8b28369 remove maanual Fibonacci calculations
22dcfea (origin/main, main) Merge pull request #2 from carlyreimer/main
f811c50 Update fib_seq.R
edbaafa Update fib_seq.R
ac48c12 Finally added a for loop and golden ratio estimate
f732cdb Seventh Fibonacci number
9db5478 Sixth number in the Fibonacci seqence
5139049 Fifth entry in the Fibonacci sequence
0c92881 Fourth entry in the Fibonacci sequence
3bb6c98 Third entry in fib_seq
e17181f Initialize Fibonacci sequence

Using git revert I specify the short SHA id from the prior commit.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git revert a0c849e
[develop 6466f85] Revert commit titled: "bad commit, plan to revert"
 1 file changed, 2 deletions(-)

The call to git log shows that a new commit was added with a message specifying the commit reverted the commit titled “bad commit, plan to revert”.

amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git log --oneline
6466f85 (HEAD -> develop) Revert commit titled: "bad commit, plan to revert"
a0c849e bad commit, plan to revert
4ef90af Test.R file added. Used to test that git checkout recalls an entire commit
ad2149a fixed merge conflict by accepting changes from label_plot branch
d0d260e Added labels to the golden ratio figure
a4c0f61 Added axis labels to golden ratio plot.
eb216a6 Merge branch 'cleanup' into develop
8b28369 remove maanual Fibonacci calculations
22dcfea (origin/main, main) Merge pull request #2 from carlyreimer/main
f811c50 Update fib_seq.R
edbaafa Update fib_seq.R
ac48c12 Finally added a for loop and golden ratio estimate
f732cdb Seventh Fibonacci number
9db5478 Sixth number in the Fibonacci seqence
5139049 Fifth entry in the Fibonacci sequence
0c92881 Fourth entry in the Fibonacci sequence
3bb6c98 Third entry in fib_seq
e17181f Initialize Fibonacci sequence
amreimer@DFGSXQDSF206801 MINGW64 /s/RTS/Reimer/Research_Best_Practices/git_practice (develop)
$ git status
On branch develop
nothing to commit, working tree clean