LESSON 1: Fundamental Operations with Git#
Lecture notes on the fundamental operations with Git. A hands-on lesson for introducing version control, tracking changes, and the tracking history.
To understand the basic operations of version control using Git.
To use Git to create repositories and commit changes.
To apply Git operations to track, reverse and delete changes in working documents.
To organise tracked changes in the Git history.
Topics:
git syntax version control repositories tracking changes untracking files gitignore undoing changes deleting and renaming files committing changes inspecting changes tags
Preparation#
Instructor’s Note
The instructor must deliver the lesson in an environment containing the latest stable version of Git. Participants should also have the latest version of Git installed on their machines.
The instructor must remove any custom configurations from the environment (i.e., Git and the shell terminal). Personal configuation may interfere with the lesson.
Adjust the code examples in this lesson to reflect any changes intruduced in the latest version of Git.
Episode 1: Git repositories for version control#
ca 50 min total
1.1.0 Welcome slides#
10 min
Introduce:
Trainers
Code of conduct
Course outline
Today’s schedule
The need for and goals of version control
The role of git as a software solution supporting these goals
1.1.1 Introduction to Git#
10 min
Create a directory for the course
Instructor’s Note
Students are assumed to have at least basic awareness of working from the command line and navigating the directory tree, but help them if necessary.
In the first section, we create the directory that will house the project. Note that depending on the environment setup, the Desktop may or may not actually be under the participants’ home directory so instructor and helpers should be ready to help learners locate it.
cd ~/Desktop/
ls
mkdir -p 2410-gitcodev/git
ls
ls 2410-gitcodev/
cd 2410-gitcodev/git/
ls
pwd
Check which shell is available
echo $SHELL
echo
Check installed version of Git
(This will be the participants’ first interaction with git, so any installation or PATH problems should show up here)
git
git --version
git version
1.1.2 Git Command Syntax and Getting Help#
10 min
We indtoduce the git help system both as a resource that they can use in future, and a way to start getting used to the CLI interface and command format.
git help
git help help
git config
git config --list
Introduce the key config parameterts, including pre-setting some that only apply on day 2. Participants may need a reminder to substitute their own details, and a quick explanation of the Windiws vs Unix end-of-line conventions (Carriage Return / Linefeed on Windows, only Linefeed on Mac / Linux / other unixoids)
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git config --global core.editor nano
git config --global core.autocrlf input # false for Win
git config --global init.defaultBranch main
git config --list
git help config
git help glossary
git help -g
1.1.3. Creating an Empty Reposiory#
10 min
Instructor’s Note
Here and throughout, it is possible to edit the file with an editor rather than appending lines with echo, however this will make the nature of the changes invisible in any gitautopush record, so is not recommended in class.
We add some content to a file and observe that, where no repo has been initialised, operations like ‘git status’ don’t do very much.
We follow this with a git init. It is important to be sure that all participants are actuall in the correct directory when they do this.
pwd
ls
echo 'first line'
echo 'first line' >lines.txt
ls
cat lines.txt
echo 'second line' >>lines.txt
cat lines.txt
git status
git init
The git status command above should return a fatal error because we are not in a repository.
ls
ls -a
ls -aF
ls -aF .git
ls
1.1.4. Q&A#
10 min
At this point, we have an empty repository, plus a single file in a working directory that has not been added to the repository. Students have had a brief view (via ls -af .git) of the inner contents of the repository proper, but should not be encouraged to dig too deeply at this point.
Episode 2: Tracking Changes in Working Documents#
ca 75 min
1.2.1 Tracking Changes with the Index#
10 min
In this section, we observe that a file in the working directory that has not been explicitly added to the repo is observed by git status, but not yet tracked. So we introduce the git add command and, alongside it, git diff.
git status
git add lines.txt
git status
ls -a .git
git diff lines.txt
Instructor’s Note
The only visible difference between the output of this and the previous ls -a .git is the appearance of the index
echo 'third line' >>lines.txt
cat lines.txt
git diff lines.txt
Output: The output of the git diff command should resemble the following. Use this opportunity to explore the format of a diff file.
diff --git a/lines.txt b/lines.txt
index 06fcdd7..20aeba2 100644
--- a/lines.txt
+++ b/lines.txt
@@ -1,2 +1,3 @@
first line
second line
+third line
We see that new additions to tracked file still need to be added to the index. The instructor may want to explain cases where this is relevant and useful.
git status
git add lines.txt
git status
git diff lines.txt
Exercise 1.1 — Tracking changes with the Index
Tracking changes with the index
5 min
Please perform the following tasks alone
The current file lines.txt
contains three lines
Revise in your terminal the commands we have used so far
Append to the file a fourth line (in the same style as the previous lines)
Check the new content of the file using…
Check whether Git realises that a change has occurred using…
Check which difference Git finds in the file using… Take note of the output of the Git commands
Follow the action that Git suggests next by using…
Same as 1.2
Same as 1.3
Same as 1.4
Take note of how the outputs of Git commands have changed
Formulate your own explanation of what you have observed The following questions are two sides of the same coin:
What did you ask Git to do?
What did Git do for you?
Answers
[No answers yet]
Tracking Directories#
10 min
Instructor’s Note
In this section, we see that while empty directories are not tracked or `seen’ by git, adding a directory to the index automatically adds its contents.
mkdir directory
ls
ls -F
git status
touch directory/emptyfile.txt
git status should not ‘notice’ the empty directory
ls -R
ls -RF
git status
git status -u
git help status
git status should report the untracked filename
git add directory
git status
git status here should report emptyfile.txt as staged but not committed
1.2.2 Not Tracking and Stop Tracking#
10 min
Instructor’s Note
In this section, we introduce the .gitignore mechanism. It is worth taking a few minutes to talk about the kinds of files associated with a project that you might not want to track, such as IDE configurations, Apple .DS_Store files, log files, test run outputs etc. We don’t want these cluttering up our git status output, or accidentally messing up our coleagues’ work environments.
First, we generate a random log file of the kind we don’t want to track.
history
history 20
history 20 >history.log
cat history.log
git status
git status reports the new, untracked file
Next, we will add a glob that matches the file to .gitignore.
echo '*.log'
echo '*.log' >.gitignore
git status
ls -a
ls -aF
git status should no longer report the file at all, although it is still present in the working directory
git add .gitignore
git status
echo 'lines.txt' >>.gitignore
cat .gitignore
Instructor’s Note
Adding lines.txt, as we can see in the git status output, does not remove lines.txt from the index, and git continues to track it, but would not start tracking it or offer it for staging if it were new.
git status
git add .gitignore
git status
.gitignore is a regular file and will be tracked unless listed in .gitignore. Whether or not this is a good idea for a particular project is up to the collaborators.
Ignore Untracked Directories#
10 min
Instructor’s Note
This section illustrates three points:
That git ignores the contents of directories that match a line in .gitignore,
That ! is a not operatory for matching purposes
That git will implement the ‘last rule standing’ after parsing .gitignore
touch directory/trackme.txt
touch directory/donttrackme.txt
ls directory/
git status
echo 'directory' >> .gitignore
cat .gitignore
git status
echo '!directory' >> .gitignore
cat .gitignore
git status
cat .gitignore
echo 'directory' >>.gitignore
cat .gitignore
git status
git help gitignore
git status
git add .gitignore
git status
git rm --cached directory/emptyfile.txt
git status
ls -FR
Exercise 1.2 — Stop tracking Changes in a File
Stop tracking changes in a file
5 min
Please perform the following tasks individually
Revise the commands we have used since the last exercise. Could you use a shell command for this?
Ask Git for the current state of the repository using…
Stop tracking the file
directory/emptyfile.txt
Caution
Be mindful of not deleting the file!
Verify the result of your action using…
Formulate your own explanation of what you have observed The following questions are two sides of the same coin:
What did you ask Git to do?
What did Git do for you?
Answers
[No answers yet]
1.2.3 Undoing Changes with the Index#
10 min
Instructor’s Note
The central idea here is the use of git restore to ‘undo’ changes to tracked files in the working directory from the index, not from the commit history, as we haven’t introduced that yet.
cat lines.txt
echo 'fifth line' >>lines.txt
cat lines.txt
git status
git diff lines.txt
git restore lines.txt
cat lines.txt
git status
git diff lines.txt
git restore lines.txt
cat lines.txt
git status
echo '!directory' >>.gitignore
ls
git status
git status -u
git add directory/trackme.txt
git status -u
git add directory/donttrackme.txt
git add directory/emptyfile.txt
git status
git add .gitignore
git status
1.2.4 Deleting and renaming tracked files and directories#
10 min
Instructor’s Note
Here we illustrate the need to use git’s utilities to delete or rename files that are tracked in the repo, if their history is to be properly maintained.
git rm --cached directory/donttrackme.txt
git status
rm -r directory/
ls -FR
git status
git restore directory
git status
ls -FR directory/
touch directory/donttrackme.txt
git status
git rm directory
git rm -r directory
git status
git rm -rf directory
git status
ls -FR directory/
git restore directory
git status
git status -u
mv directory/donttrackme.txt directory/trackne.txt
git status -u
# use the command `git mv <oldname> <newname>`
# lines.txt Lines.txt
git status -u
git mv lines.txt Lines.txt
git status -u
Exercise 1.3 — Renaming Tracked Files
Renaming tracked files
5 min
Please perform the following tasks individually
Revise the commands we have used since the last exercise. Could you use a shell command for this?
Ask Git for the current state of the repository using…
Rename the file
lines.txt
asLines.txt
using…Verify that the working tree contains
Lines.txt
using…Verify that Git tracks
Lines.txt
using…
Answers
[No answers yet]
Episode 3: Organizing Tracked Changes in a History#
ca 75 min
Instructor’s Note
This is a critical moment in the lesson. We have introduced the index, as a representation of the project at a point in time. Now we begin to develop the idea of the repository as a sequence of such staged changes over time that culminate in the current state of the project (or branch, but we haven’t introduced that concept yet), HEAD.
1.3.1 Commiting Changes with a Configured Identify and a Message#
10 min
We introduce the ‘git commit’ command as an commitment of the state of the index at some point in time.
We note that a commit MUST be accompanied by a descriptive message
cat Lines.txt
git diff
git status
git commit -m 'Add first four lines' Lines.txt
We see next that a succesful commit gives us a ‘clean’ index with no stages changes, but we can look at a log and see the history.
When we look at the log, we see the ‘long form’ commit ID for the commit we just made, which is effectively guaranteed to be globally unique.
git status
git log
Exercise 1.4 — Commit Changes in a Tracked File
Commit changes in a tracked file
5 min
Please perform the following tasks individually
Check if .gitignore
is ready to be committed using…
Commit .gitignore
using…
Attention
DO NOT forget the commit message describing your action
Answers
git status
git commit -m 'Add .gitignore' .gitignore
git status
rm -r directory # to keep things clean
git status
ls
git log
Exercise 1.5 — Follow the state of the repository in the commit routine
Follow the state of the repository in the commit routine
5 min
Please perform the following tasks individually.
The baseline
Revise the commands launched since the last exercise using…
Check the output of
git status
The working tree
Append the fifth line to
Lines.txt
using…Repeat 1.2 and compare its output with the previous
The index
Stage the changes of
Lines.txt
in the index using…Repeat 1.2 and compare its output with the previous ones
The history
Store the changes of
Lines.txt
in the history using…Repeat 1.2 and compare its output with the previous ones
Look up and parse the commit history using…
Formulate your own explanation of what git status showed you The following questions are two sides of the same coin:
What did you ask Git to do?
What did Git do for you?
Answers
# Procedure for exercise 5
echo 'fifth line' >>Lines.txt
cat Lines.txt
git status
git add Lines.txt
git status
git commit -m 'Add fifth lines' Lines.txt
git status
history
git log
1.3.2 Inspecting Changes Using the History#
Exercise 1.6 — Follow the state of the index in the commit routines
Follow the state of the index in the commit routine
5 min
Please perform the following tasks individually
The baseline
Revise the commands launched since the last exercise using…
Check the output of
git diff
The working tree
Append the sixth line to
Lines.txt
using…Repeat 1.2 and compare its output with the previous
The index
Stage the changes of
Lines.txt
in the index using…Repeat 1.2 and compare its output with the previous ones
The history
Store the changes of
Lines.txt
in the history using…Repeat 1.2 and compare its output with the previous ones
Look up and parse the commit history using…
Formulate your own explanation of what git diff
showed you
The following questions are two sides of the same coin:
What did you ask Git to do?
What did Git do for you?
Answers
# procedure for exercise 6
git status
git diff
echo 'sixth line' >>Lines.txt
git diff
git add Lines.txt
git diff
git diff Lines.txt
git commit -m 'Add sixth line' Lines.txt
git diff
git log
git log --oneline
git status
echo 'seventh line' >>Lines.txt
git diff Lines.txt
git add Lines.txt
git diff Lines.txt
git status
git log --oneline
git diff HEAD Lines.txt
git diff e278702 Lines.txt
git diff HEAD~1 Lines.txt
git log --oneline
git diff 7f2ca Lines.txt
git diff HEAD~2 Lines.txt
git diff HEAD~3 Lines.txt
git diff HEAD~7 Lines.txt
git diff Lines.txt
git diff HEAD~3 Lines.txt
git diff HEAD HEAD~1 Lines.txt
git diff HEAD~1 HEAD Lines.txt
git diff HEAD~4 HEAD~2 Lines.txt
git diff HEAD~3 HEAD~2 Lines.txt
git log
#
pwd
git status
git log --oneline
git diff Lines.txt
git diff HEAD Lines.txt
git diff HEAD~1 Lines.txt
git diff HEAD HEAD~1 Lines.txt
git diff HEAD~1 HEAD Lines.txt
diff HEAD HEAD Lines.txt
git diff HEAD HEAD Lines.txt
git diff HEAD~2 HEAD~2 Lines.txt
Break#
10 min
Exercise 1.7 — Explore the changes recorded in the history
Explore the changes recorded in the history
7 min
Please perform the following tasks individually
The baseline
Revise the commands launched since the last exercise using…
Perform the commit routine
Append the seventh line to
Lines.txt
using…Stage the changes of
Lines.txt
in the index using…Store the changes of
Lines.txt
in the history using…
As many times as you like
Check the history using…
Compare different versions of
Lines.txt
using…
Formulate your own explanation of what you have observed The following questions are two sides of the same coin:
What did you ask Git to do?
What did Git do for you?
Attention
Are there shortcuts to do the same with less typing?
Answers
# No answers yet
Exercise 8 is an optional exercise about comparing differences in the history.
1.3.3 Undoing Changes with the History#
10 min
Instructor’s Note
This topic involves using git restore
.
We have introduced the HEAD~x notation in the exercises above, and we will introduce both the short form commit ID and the tag mechanism shortly. Here we see that using the -s flag we can specify a source (commit) from which to restore a specified file.
git restore -s HEAD~2 Lines.txt
cat Lines.txt
git status
git restore -s HEAD Lines.txt
git status
Lesson Summary#
10 min
Give a short wrap up about what has been learned. Encourage questions and perhaps give a ‘teaser trailer’ for lesson 2.
Instructor’s Note
Remember to coordinate with the trainer for day 2 to ensure that they have a repository that begins day 2 with the same state as the learners, either by their rerunning the command log, or by physically copying your repo in a ZIP or tarfile.