Basic Git#
Learning Objectives#
Understand the core concepts and functionalities of Git
Execute fundamental Git commands including
init
,clone
,status
,diff
,log
,add
,commit
, andcheckout
Explain the concept of Gits three locations and how changes flow through them
Utilize the
.git
directory to manage repository metadataImplement file ignoring practices using
.gitignore
Recognize the significance of Gits fourth location and its role
Perform basic troubleshooting and seek help for Git commands
We’re going to review some git commands used to create a basic series of snapshots of our code. This will cover setting up a repository, seeing the status and history, creating new snapshots, and restoring previous snapshots of the directory. We’ll also look into what’s happening “behind the scenes” to enable this workflow.
We’ll cover commands for setup (init
and clone
), info (status
, diff
and log
), making snapshots (add
and commit
) and loading snapshots (restore
and checkout
).
Getting Help on Commands#
Recall that we can see information on git commands with the -h
flag.
For example, to see the help for commit
, use
git commit -h
Basic Git Recap#
Here is a quick summary of the commands we will cover in this lesson:
git init
will start tracking changes in the current directory.git clone
will create a copy of a repository, such as from GitHub.git status
will show us differences in the workspace relative to the last snapshot.git diff
will show the line-by-line differences relative to the last snapshot.git log
will show us all the previous snapshots that led to the current state of the repository.git add
will mark changes to be included in the next snapshot.git commit
will make a new snapshot from the files marked withadd
.git restore
will undo the actions ofadd
, removing the changes from the next snapshot.git checkout
will load a previous state of the code.
Before looking at the details of these commands, we’ll briefly discuss how git is storing the information required for tracking the version history.
Behind the Scenes: Git’s Three Locations#
Conceptually, it’s helpful to thing of git commands managing the state of three locations:
Work directory
Staging area
Local Repository
The Work Directory (or workspace) is simply the files you can see in the root directory (with the exception of .git/
).
If we weren’t using any form of version control, we would have to be very careful with changes made to our files.
The Staging Area (or index) represents the changes made to our files that will be used for the next snapshot.
The Local Repository (or repository) contains all the snapshots of our files.
The key concept of version control with git is moving changes between these three locations.
Starting out: init
and clone
#
If we have a directory that isn’t currently managed by git (and isn’t a subdirectory of one that is),
git init
will create a (hidden) directory called .git/
and allow us to start adding files and creating snapshots.
If a codebase is available over a network (such as on GitHub), we can get a local copy of the repository and its history with
git clone <repository>
where <repository>
is a URL or path to the repository.
By default this will get the full repository, including the full history of the default branch.
All previous snapshots will be available locally (stored in the .git/
directory)
Getting information: status
, diff
and log
#
To get general information of changes that have been made to the files since the last snapshot, use
git status
With regards to the “Three Locations”, it will tell us how the Work Directory differs from the Staging Area and the most recent commit in the Local Repository.
The status
command also shows information on the branch, any linked remote repositories, and updates from some more involved git commands.
We can get more detail about what changed with the diff
command:
git diff
Without any additional arguments, diff
shows us the line-by-line changes between the Work Directory and the Staging Area.
We can supply additional arguments to file differences between commits.
To see the history of the repository we can use
git log
This will start paging the contents of the log.
We can step through extra pages with the Space
key, or stop the pager entirely with q
.
The basic form of the log is not always the most useful, so we can modify this with arguments to change
the range and number of commits (e.g.,
git log -n 2
)which commits are shown (e.g.,
git log --simplify-by-decoration
)the format of the log output (e.g.,
git log --oneline
).
We can see the full list of arguments from the online help.
Try different combinations of the following arguments.
--oneline
(show a oneline summary of the commit)--all
(show all commits, not just those in the current commit’s history)--graph
(render a graph to visualise branching and merging)
Some other useful arguments are --grep
(search for specific changes), --patch
(show line-by-line changes) and --stat
(summarise how many lines in each file changed).
Creating snapshots: add
and commit
#
In order to prepare a snapshot, we need to tell git which changes the stage. This is done with the add command
git add <pathspec>
where <pathspec>
is a path to a file, such as
git add README.md
This will move changes from the specified file from the Work Directory to the Staging Area.
We can also use a glob pattern to match all matching files, such as adding all files ending in .txt
with
git add *.txt
We can move all changes to the Staging Area with the --all
argument, although this often results in staging changes we didn’t want tracked.
To remove a file from the index, we can use restore
, for example
git restore --staged README.txt
When we’ve added all the changes we want to the Staging Area (and checked the output of git status
) we can create a new commit with
git commit --message "Commit message here"
# equivalently git commit -m "Commit message here"
This will create a new commit in the Local Repository from the Staging Area.
If we omit the -m
/--message
argument, git will open an editor to prompt us to enter a message.
This will typically be either nano or vim - examples of both will be demonstrated in the session.
Restoring previous snapshots: checkout
#
To see a previous version of the code, we need an ID of the version.
This will either be from git log
, or a named reference (typically the name of a tag or branch, or a modification of HEAD
).
One example of a reference is HEAD^
, being the commit before the most recent one (HEAD
is the current commit, HEAD^
is the parent of that commit).
The command
git checkout HEAD^
will extract the commit from the Local Repository and change the Working Directory to match it.
To get back to the most recent snapshot, we can use
git checkout main
The .git
Directory#
The .git
directory contains all the local files that git uses.
local options (
.git/config
)information on the most recent snapshot (
.git/HEAD
)binary objects containing past snapshots and the staged files (
.git/objects
)references to any tags, branches and remotes (
.git/refs/
)
Almost all changes made to .git/
should be handled by git commands (we will see a few rare exceptions later).
Ignoring files#
We can tell git that we never want to track changes in a file by adding it to a special file named .gitignore
.
This file is typically tracked by git itself.
With this file in place, we wont get prompts about changes to this file from git status
.
It will also be ignored by commands such as git add --all
and git commit --all
, although it’s best not to rely on this in case you move to a previous version with an old .gitignore
file.
There are times when we have files to be ignored on the local system but we don’t want them stored in the repository in the .gitignore
.
In these cases we can alternatively use .git/info/exclude
- one of the rare exceptions to “leave .git/
alone”.
Git’s Fourth Location#
In addition to the workspace, index and local repository, we frequently work with remote repositories, often described as git’s fourth location.
Changes are moved between the local and remote repository with push
and fetch
/pull
.
These commands will be used extensively in the second session.
Summary#
We have taken an in-depth look at the basic git commands that allow us to create a chain of commits, and review the history of our files. In the next lesson we’ll be looking at branching, which allows us to maintain and track multiple versions of our code.
Exercise#
Explore the help files of some of the commands we’ve seen in this lesson. Would any of these be worth creating a new alias for?
Discuss what you’ve found with your course mates.