Git 101
Prelude: Installing Git1
Open Terminal and enter git --version
to see if you have Git installed. A message like git version 2.20.1 (Apple Git-117)
indicates that you are ready to use Git. If you don’t have Git installed, then an alert will appear displaying The "git" command requires the command line developer tools. Would you like to install the tools now?
There are three options:
-
Click Install and get the Command Line Developer Tools. This hassle-free experience will give you the Apple version of Git.
-
Install Xcode, which includes the Command Line Developer Tools.
-
Click Cancel and get the latest version of Git directly from the developers .
If you already have Git installed, you can follow these instructions to update to the latest version.
Git on your Local Machine
- Creating a New Git Repository Using
git init
Exercise: create a new directory named
GitTutorial
and navigate inside it.
Once your present working directory is GitTutorial/
, simply type git init
to begin using Git for version control.
Exercise: type
git init
Terminal will output Initialized empty Git repository in /path/GitTutorial/.git/
where path
specifies the location of GitTutorial/
. This empty Git repository is hidden; note the differences of ls
and ls -a
in GitTutorial/
2.
- Saving Using
git add
andgit commit
The command git add .
tells Git to take a snapshot of the current status of the directory3.
Exercise: type
git add .
This snapshot is now stored in a temporary staging area which Git calls the index and this process is called staging. You can permanently store staged files with git commit
. One of the benefits to using Git is that you can tag each commit with a message4. This should be something short and informative, e.g. “initial commit” or “adding June data”. git commit
on its own will prompt you to provide a message; alternatively, you can use git commit -m "message"
Excercise: Commit your current directory to your local machine.
- Making Changes to Your Git Repository
Suppose you add new files/directories or make changes to existing files in your Git repository. These changes are not automatically stored by Git; you must tell Git precisely what you want to add every time you want to make a commit. Git is very flexible in what it allows you to commit: you can choose to commit a single modified file, everything that has been modified, or anywhere in between.
git add file
stagesfile
only.git add file1 file2
stagesfile1
andfile2
; this is extendable to any number of files. Alternatively, you could usegit add file1
andgit add file2
as separate commands.git add -A
stages changes from ALL tracked and untracked files.git add .
stages new and modified files but not deleted filesgit add -u
stages modified and deleted files but not new filesgit commit -a
is equivalent togit add -u
andgit commit -m "message"
Remember that with the exception of the last command, you must commit your files before Git permanently saves the changes!
Exercise: Create and modify some dummy files and play around with various
git add
andgit commit
commands to make changes to your repository.
- Branches: Creating Diverging Workflows with
git branch
andgit switch
One of the most useful features of Git is its ability to create branches, new lines of development that can build on existing work without messing anything up 5. For example, you might want to experiment in a sandbox environment before making a (more) permanent change to your repository, or you may want to create a separate workflow line for your personal contributions to a group project. Changes on one branch do not automatically show up on another branch.
The command git branch branch_name
creates a branch called branch_name
. git branch
without specifying branch_name
will list existing branches. The primary/original branch is named master
and the branch you are currently on is marked with an asterisk (*
). The command git switch branch_name
switches your repository to branch_name
as long as a branch with that name exists.
Exercise: type
git branch
. Then create a new branch calledfeature
, usegit switch
to switch tofeature
, and typegit branch
again.
Exercise: create a new file or modifiy an existing file and commit it on the
feature
branch. Switch back tomaster
to verify that these changes are isolated to thefeature
branch.
- Integrating Separate Workflows with
git merge
6
Exercise: make and commit a different change to the
master
branch
At this point the two branches have diverged, with different changes made in each. Visually, the repository looks something like this:
The command git merge branch
merges the changes made on branch
to your current branch, typically master
. It is recommended that you confirm the receiving branch with git branch
before merging!
Exercise: merge
feature
tomaster
In this simple scenario, merging should not have caused any issues, and the following image illustrates the new status of your repository 7:
Merge conflicts, however, can prevent Git from merging two branches automatically. This can happen for a number of reasons, for example both branches have different changes made to the same line(s) of a particular file or one branch has made changes to a file that the other branch has deleted 8.
At this point, you could delete the feature
branch with git branch -d feature
. This command ensures that the changes in the feature
branch are already in the current branch. Conversely, if you develop on a branch crazy-idea
, but then regret it and want to delete all of the changes made on this branch, you can delete it with git branch -D crazy-idea
.
- It is Easy to Git 9 Lost: Fixing Confusion with
git status
andgit diff
If you have made a lot of changes to your repository or simply can’t remember what you have staged, the the command git status
can help to reorient yourself. According to the
documentation
,git status
displays paths that have differences between the index file and the current HEAD commit, paths that have differences between the working tree and the index file, and paths in the working tree that are not tracked by Git. The first are what you would commit by running git commit
; the second and third are what you could commit by running git add
before running git commit
. git status
also reminds you on what branch you are currently working.
It is also worth mentioning that git diff
can be used to show the changes made to modified files.
Excercise: Continue playing around with git add
, git reset
, and git commit
on dummy files, but this time also use git diff
and git status
to see how different actions change your repository.
- Exploring History:
git log
,git checkout
, andgit reflog
The command git log
displays the history of your commits, with more recent commits at the top. Use the arrow
keys to scroll and press q
to exit.
Exercise: Type
git log
Observe that each commit lists the author, date, branch and commit message, as well as the associated 40-character checksum hash. This hash is one of the most powerful features of Git, as it enables you to switch to a different state of the repository. The command git checkout hash
, where hash
is the beginning (first 5-15 characters) of a particular commit, will change the contents of your repository from its current status to what it contained at that commit. This is best used when you merely want to look at the contents from this commit; see below if you want to make changes from this commit.
At this point, it is worthwhile to define HEAD
, a term which you may have already noticed. HEAD
is simply a reference to the current (most recent) commit on the current branch. If you are not on the latest commit - meaning that HEAD
is pointing to a prior commit in history - then it’s called detached HEAD
.
Exercise: use
git checkout
to switch your repository to a previous commit.
The command git reflog
displays the history of changes which updated HEAD
.
Exercise: type
git reflog
In addition to git checkout
, there are a few more ways to move around your repository’s commit history:
git checkout HEAD@{...}
will moveHEAD
to the commit {…} as described bygit reflog
git checkout -
switchesHEAD
to its position before the previouscheckout
10git checkout branchname
returns to the commit that is the head ofbranchname
Exercise: Move around your commit history using
git log
,git reflog
, andgit checkout
- Creating Branching Timelines
Now suppose that instead of merely viewing the contents of a past commit, you want to use that commit to begin a new branch. Git allows (at least) two ways to do this:
git checkout
to move to the desired commit followed bygit switch -c <new-branch-name>
git checkout -b <new branch> <commit_id>
(this essentially combines the two distinct steps of the previous method into one)
Exercise: Create a branch from
master
at a past commit and commit some changes on this branch. Attempt to merge this branch with the most recent commit onmaster
.
- Undoing Commits and Changes:
git reset
andgit revert
Suppose you staged the wrong file to commit, or you staged the correct one prematurely. git reset file
will remove file
from the index. git reset
on its own will unstage all due changes.
Alternatively, suppose that you not only staged the wrong file(s), but you also committed the changes. git revert HEAD
tells Git to create a new commit which is an inverse of the previous commit: anything deleted in the most recent commit will be added, and anything added in the most recent commit will be deleted. This is ideal for published changes because it preserves the true history of the repository. git revert
can also be used to undo multiple commits, using either git <hash-or-ref>
to revert to a specific commit or git revert HEAD~N
where N
is the number of commits you wish to revert (e.g. git revert HEAD~2
reverts two commits).
git revert
does not delete the undesired commits; if this is your intention, use git reset --hard <hash-or-ref>
The --hard
option reverts everything back to the specified commit, including reference pointers, the staging index, and your working directory. Thus not only does this command revert to a previous commit, it also deletes all working changes. To avoid losing any working changes, you can use stash
to save your working changes before resetting and stash pop
to recover the changes after resetting.
git reset
also has a --soft
option that works only affects the commit history, not your working directory or staging index. This is likely the best option if you have uncommitted changes that you want to keep.
Exercise: play around with
git reset
andgit revert
to undo changes made to your repository.
- Move, Copy, Rename, and Delete:
git mv
,git cp
, andgit rm
Git has built-in commands to move, rename, copy, and delete files. git mv
, git cp
, and git rm
perform analogously to mv
, cp
, and rm
. The benefit of using these Git commands is that they automatically add the file to the index so that you only have to commit the changes.
Exercise: play around with
git mv
,git cp
, andgit rm
- Fully Deleting a Git Repository
Finally, suppose that after a series of commits, branches, and merges, everything is up-to-date on and accurate on master
and you want to start fresh with a new Git repository. The command rm -rf .git
deletes the .git/
repository and leaves only the working directory. git init
can be used on this clean directory to start a new workflow. As with any use of rm
, use with caution!
Aditional Resources
If you want Git help directly in the terminal, type man gittutorial
or man giteveryday
.
If you made a mistake and are unsure how to fix it, check out Oh Shit, Git!?
For a textbook written by the authors of Git, see Pro Git .
1 For more information, visit Macworld .
2 Recall that hidden files/directories should not be modified unless you know what you are doing - the Git repository is hidden for a reason!
3 Recall that .
refers to your current directory.
4 A note on commit messages : Though not required, it’s a good idea to begin the commit message with a single short (less than 50 character) line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git.
5 There is a lot that goes on beyond the scenes that makes Git’s handling of branches much more efficient than other version control methods.
6 Images courtesy of Atlassian
7 The command gitk
shows a graphical representation of your specific history.
8 For more information on handling merge conflicts, visit this tutorial .
9 Pun intended.
10 Note the similarity to cd -
.