Lab4: Time Travel
Objectives¶
The goal of this lab is to understand the following commands:
A quick review¶
When you work on a new machine
You can create a new PAT and use
git cloneto clone the remote repo onto your machine.Check that Git is correctly configured on your machine with
git config --global user.nameandgit config --global user.email.
Time travel¶
We learned that Git uses a commit graph to represent the different versions of our project over time. Now, we are going to learn how to navigate through this graph.
Checkout¶
We can navigate through the different nodes of this graph, which means we can go back to different states of our repository in the past, saved by commits. Before you start, make sure your repository is clean (all changes are in a commit).
Run
git checkout <commit hash>using the commit hash of an old commit. Your command could look likegit checkout abc0123, for example.
Observe the state of your (old) repo.
Go back to the most recent node (and leave the detached HEAD state) by running
git checkout main.
git checkout -
git checkout -The git checkout - command lets you go back to the last node you visited (before the current node where HEAD is).
You can also use
git diff <commit hash>to see the differences between your current working tree and the state of your repo after an old commit.Travel through your commit graph and observe the state of your repo (with
checkout,diff,status, andgraph), then come back to the present once you have mastered this time travel.
Stash¶
To prepare for our time travel, we are going to learn how to keep the current changes from the present that are not yet in our commit graph, because going back to the past will change the reality observed in our working tree.
Before you start, check the state of your commit graph with
git graph.Create a
Lab4/directory with atime-travel.txtfile containing whatever content you want.Run
git addandgit committo record these changes.Use
git graphto confirm that a new node has been added with your commit message.Modify the contents of
time-travel.txtwithout runninggit addorgit commit.Run
git stashand observe the contents of this file.
git stash
git stashWhen we need to temporarily interrupt our work session to time travel, for example (go back to the repository state in the past), we must follow clean-code principles such as “only commit when the code compiles or passes the tests”.
Since no commit has been made yet, our changes do not exist in the commit graph, but we still want to keep them.
The git stash command stores the current changes in a stack (like a stack of plates) without doing add or commit.
The exact effects of this command and its options will be covered later in this lab and in the next lab.
Run
git stash popand observe the contents oftime-travel.txt.
git stash pop
git stash popThe changes in the “plate” on top of the stack are restored into the working tree, and that plate is removed from the stack.
The git stash stack will be studied later with the introduction of branches.
Create three files
modified-time-travel.txt,staged-time-travel.txt, andignored-time-travel(without an extension) containing whatever content you want.Add, commit, push, and verify that the changes are on the remote repo, except for
ignored-time-travel, which is ignored (if your.gitignoreis correctly configured to ignore files without an extension; otherwise, fix your.gitignore, clean up your remote repo, and start again from step 8).Create a new file
untracked-time-travel.txtinLab4/with the content that you want without runninggit add.Modify the contents of
modified-time-travel.txtwithout runninggit add.Modify the contents of
staged-time-travel.txtand rungit add staged-time-travel.txtwithout runninggit commit.Modify the contents of
ignored-time-travel.
At this point, make sure you have a new untracked file (untracked-time-travel.txt), a modified file that was already tracked (modified-time-travel.txt), a modified file that is staged (staged-time-travel.txt), and a modified but ignored file (ignored-time-travel).
Run
git stashand observe the contents of the four files. Which changes disappeared, and which ones stayed?Run
git stash popto restore all your changes.Run
git stash -uand observe the contents of the four files. Which changes disappeared, and which ones stayed?Run
git stash popto restore all your changes.This time, run
git stash -aand observe the contents of the four files. Which changes disappeared, and which ones stayed?Run
git stash popto restore all your changes.
Now, you should know which changes are stored in the git stash stack.
git stash -u and git stash -a
git stash -u and git stash -aBy default, git stash saves only changes to tracked files and changes present in the staging area.
If you want to include changes in a new file, you can use git stash -u (short for git stash --include-untracked).
If you also want to include changes in ignored files, you can use git stash -a (short for git stash --all).
Run
git checkout <old commit hash>and observe the error message.
The danger of time travel
If you run git checkout while there are changes that are not in the git stash stack, Git warns you that they might be lost.
It is therefore recommended to use git stash -a to include all your changes before running git checkout.
Add, commit, and push all your changes.
Reset¶
Le voyage dans le temps nous rend parfois nostalgiques d’un meilleur passé.
Malheureusement, nous ne pouvons que l’observer avec une tête détachée.
Si seulement nous pouvions changer la réalité et réinitialiser...
Create a
reset.txtfile containing a line of your choice, then add and commit without pushing.Add a second line to
reset.txt, then add and commit without pushing.Check
git graphandgit status.Run
git reset HEAD~1to remove the last commit.Check
git graph,git status, and the contents ofreset.txt.
git reset
git resetThe git reset command removes the latest nodes from the commit graph.
You can also run git reset HEAD~<number> to undo the last <number> commits.
Add and commit without pushing your changes once again. Then make changes to
reset.txton the following lines, making a different commit without pushing for each line.
Now, you should have several consecutive commits that modify the contents of reset.txt.
Choose a commit in the past (after the creation of
reset.txt) and rungit reset <commit hash>. Then checkgit graphandgit status.
git reset <commit hash>
git reset <commit hash>Instead of doing git reset HEAD~<number>, you can also use git reset <commit hash> to remove all commits that come after a specific commit.
Create a few more commits by modifying
reset.txtwithout pushing.Run
git reset --softwithHEAD~<number>or<commit hash>and checkgit graphandgit status. What is the difference between--softand the default behavior ofreset?Create commits again without pushing.
Run
git reset --hardwithHEAD~<number>or<commit hash>and checkgit graphandgit status. What is the difference?
--soft, --mixed, and --hard
--soft, --mixed, and --hardgit reset has three main options: --soft, --mixed, and --hard.
--softundoes commits while keeping their changes in the staging area.--mixedis the default behavior ofresetand keeps the changes from the undone commits in the working tree.--harddeletes both the undone commits and their changes.
We insist that commits and deletions must be done locally before being pushed to the remote repo. Why?
Does that mean a synchronized commit can never be “undone”? We are going to see how to undo a commit that is already on the remote repo.
Add, commit, and push all your changes.
Revert¶
Et je croyais pouvoir modifier la réalité...
Alors que ce n’est que ma réalité...
Comment puis-je annuler mes commits erronés ?
Si je les ai déjà partagés avec le monde entier.
Create a
revert.txtfile with one line of text and make a commit with push.Add a second line to
revert.txtand make a commit with push.
Let’s imagine that the second line added is a mistake. We are going to revert this commit while keeping the history.
Run
git revert HEAD. Enter a message in the editor, just like for a commit message.Check the contents of
revert.txt,git status, andgit graph.
git revert
git revertThe git revert command creates a new commit that undoes the changes from previous commits.
The different options of git revert will be explored later in this lab.
Experiment with a new commit and
git revert HEAD --no-edit, then check the contents ofrevert.txt,git status, andgit graph.
git revert --no-edit
git revert --no-editHere, you will notice that a new commit has been created with the default message Revert "<message of the reverted commit>".
Make at least three changes in
revert.txtwith add, commit, and push for each line separately.
We can also revert multiple commits. Each undone commit will be accompanied by a revert commit.
Run
git revert HEAD~3..HEAD --no-editto revert the last three commits. Check the contents ofrevert.txt,git status, andgit graph.
git revert HEAD~<number>..HEAD
git revert HEAD~<number>..HEADYou can omit the --no-edit option to add a message for each reverted commit. You could also have used git revert -n HEAD~3..HEAD (-n for --no-commit), which does not automatically create multiple commits, then run git commit -m "<message>" to create a single commit (instead of three) with the message you want.
Experiment with multiple commits, then
git revert -n HEAD~3..HEADandgit commit -m "<message>", while checking the contents ofrevert.txt,git status, andgit graph.
Since you are not deleting any commits but creating new commits that “undo” old ones, there is no risk to the remote repo history.
Make sure your repository is clean. Go back to the objectives and check off the points you have mastered. Practice the commands and concepts you have not yet fully understood. Ask your instructor for help if needed.
Quiz!
Don’t forget to complete the lab quiz on Moodle!
Teaser: traveling between parallel universes
In the next lab, we will see how to create parallel universes (branches), travel between different universes, and merge universes into a single one!