Covered commands:
git config
- creating a repository with
git init
orgit clone
git clone
git init
git add
git commit
git status
git log
git checkout
We want git to record changes with authorship, so it's clear who changed what
and when that happened. There are many options that we can set with git config
, but today we'll refresh the basics
Identity:
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"
Preferred Text Editor (used by git to modify commit messages, among other things):
git config --global core.editor "atom --wait"
For today, we'll be using atom. But in the future you can look up how to set your preferred editor here
In the case of atom or any other graphical user text editor we need to set the editor to wait (with --wait or -w) to make sure that git waits until the file is saved and closed to finish commiting the file.
An aside: we can change git settings for repositories only, or for the entire
system. This is up to your preference, but perhaps you have a project associated
with a lab and want to change your user e-mail only for that particular project.
You'd change the user.email
option in the repository rather than for your
whole user space. Changing config options is up to your use and needs.
- locally with
git config [options]
orgit config --local [options]
. The config options are stored in$REPOPATH/.git/config
. Your current working directory will need to be a a working git repository in order to set config options at this level. - globally (for a particular user) with
git config --global [options]
. The config options are stored in~/.gitconfig
- for windows:
C:\Users\username
- for apple:
/Users/username
- for linux:
/home/username
- for windows:
- system-wide with
git config --system [options]
tips:
- if you change your user config settings to and e-mail not associated with your remote (like github), you might have some issues pushing.
- you can modify your config on the command line or by editing the config files mentioned above.
- you can check your config settings by opening the config file or by executing
git config --list
orgit config -l
- To initialize a new repository from the command line:
git init
(this option doesn't require internet access or a github account) - We can also get an existing repository from a remote server with
git clone https://github.com/username/reponame.git
. This command will create a new folder called reponame in your current working directory and will copy the contents of the remote repository into that folder. (this option requires internet, and depending on permissions you may need a github account)
We can check that a folder we're in is a git repository by executing git status
. If the folder isn't a repository, git will tell us fatal: Not a git repository (or any of the parent directories): .git
. We can also check by
listing all files and folders (including hidden ones) in our directory with ls -a
. A git repository will have a .git/ folder that contains the history of
our repository.
tips:
- each repository should be in its own folder, not in a subdirectory of another version-controlled folder
- every time you work on a project on a new computer you'll need to update your git config settings to ensure you have proper credit for the things you author
- if you have different config settings locally vs. globally the more refined config settings will override something more global. In that vein, local > global > system.
If you haven't yet, make a new project folder, navigate into it and then initialize the repository.
$ mdkir dissertation
$ cd dissertation
$ git init
Initialized empty Git repository in /Users/madicken/repos/dissertation/.git/
Our most used commands in git will be the following:
git add
will add a file to the staging areagit commit
will save or commit our staged files togit status
will return information about the existing state of our repository.git log
will show the commit log
Now that we've initialized an empty repository in /dissertation/
, we can
check the status:
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
A file in a git repository can be in one of four states: untracked, unmodified, modified, and staged. When we go through the process of editing a file, adding it, and committing it, we're cycling through these different states. The figure below from the git book shows this process visually.
These states are reflected when we use git status
to look at
the status of a directory. Let's create go through this process with regular
git status
checks and see what this looks like.
$ vi AUTHORS.md
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
AUTHORS.md
nothing added to commit but untracked files present (use "git add" to track)
$ git add AUTHORS.md
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: AUTHORS.md
$ git commit -m 'add my name to author list'
[master (root-commit) 96c67ed] adding my name to author list
1 file changed, 1 insertion(+)
create mode 100644 AUTHORS.md
$ git status
On branch master
nothing to commit, working tree clean
Here we've seen AUTHORS.md go from untracked -> modified -> staged -> unmodified. We can check the log to see what our history looks like.
$ git log
commit 96c67ed10232a25c6d8a1e6eb64e0c25b54d7e34 (HEAD -> master)
Author: Madicken Munk <madicken.munk@gmail.com>
Date: Mon Jan 14 16:53:20 2019 -0600
add my name to author list
The series of numbers and letters in the first line after the command is what is known as the commit hash:a unique identifier that is used to mark this particular snapshot of our repository. Note that this is the same identifier that git returned to us when we committed our changes, but only the first seven characters were shown.
If we choose to commit with git commit
and no arguments, git will enter into a
text editor. This is useful if we have a large set of changes that we want to
describe more fully. The first, short commit message should be the TL;DR of our
changes, while the longer detailed message might list specifics.
short, descriptive message for my dev work
Here I describe in detail a little more about the dev work that I
did. Maybe I added a few new functions. I could list them here. Of
course, since I'm only editing my dissertation this longer form of
the commit message might not be as relevant to my work.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Changes to be committed:
# modified: AUTHORS.md
#
When we save and exit the editor after writing out our commit message this way, git will return a similar message as before.
$ git commit
[master 2d701bb] add my name to author list
1 file changed, 1 insertions(+)
Tips:
- when committing I personally like to use the shorthand
git commit -m "This is my message"
, but you can be more verbose withgit commit --message
or enter straight into a your preferred text editor withgit commit
. You might prefer to go into the text editor if you have a lot of changes to describe. - any of the git commands can be followed a
--help
or-h
option to learn more about what options are available to you - If you're working with changes in many files, you can add all updated files to
the staging area with
git add -u
and all files to the staging area withgit add -a
The log will tell us about the history of the branches that we're on. I'm going
to step out of the toy repository we've been working in to something a bit more
complex to demonstrate the power of git log
and its ability to tell us about
our history.
A standard execution of git log
will show us as much of the log that will fit
into our shell's buffer at a time. At the bottom of the buffer you should see
a :
.
This is the shell prompting you for navigation. You can page up or down within
the log, or you can exit by pressing you Q
key. Some of the log messages that
were in the buffer may be printed in the shell when you exit.
Maybe we're only interested in the last few log messages. We can print only a
designated number with git log -n [number]
. Here I am printing the three most
recent commit messages on matplotlib's master branch:
~/repos/matplotlib(master) $ git log -n 2 --sparse
commit a552780fa074feaa54750a9dbe935392f24f6576 (HEAD -> master, origin/master, origin/HEAD)
Merge: a728b91c9 4ef57532d
Author: Nelle Varoquaux <nelle.varoquaux@gmail.com>
Date: Mon Jan 14 13:21:39 2019 -0800
Merge pull request #13107 from anntzer/bboxbase
Cleanup BboxBase docstrings.
commit a728b91c958f53eae1e41d38b2b6006f54666bcf
Merge: 2502fe6f0 2585d9fe2
Author: Nelle Varoquaux <nelle.varoquaux@gmail.com>
Date: Mon Jan 14 13:20:18 2019 -0800
Merge pull request #13108 from anntzer/capitalize-docstrings
Capitalize some docstrings.
Sometimes we don't need the entire log message printed out in such a detailed
format. We can get a condensed version of the log with the --oneline
flag.
Here's an example printing the last 10 log messages from matplotlib's master
branch:
~/repos/matplotlib(master) $ git log -n 10 --oneline
a552780fa (HEAD -> master, origin/master, origin/HEAD) Merge pull request #13107 from anntzer/bboxbase
a728b91c9 Merge pull request #13108 from anntzer/capitalize-docstrings
2502fe6f0 Merge pull request #13115 from timhoffm/check-sphinx_copybutton
46350268f Merge pull request #13151 from timhoffm/doc-radiobutton
57d031d23 Merge pull request #13178 from anntzer/derole
beed2d80e Merge pull request #13089 from anntzer/quivermatrix
aef686b43 Merge pull request #13179 from anntzer/axis_artist-deprecated
d9d3bdb49 Avoid calling a deprecated API in axis_artist.
bacea6a99 Remove :func: markup from mlab docstrings.
6b3c015da Merge pull request #13047 from timhoffm/doc-contourf-extend-cmap
We can return to previous states in our repository with the commit hashes that
are listed in the log. We can navigate in our history and see previous versions
of our repository. To do this, we can use git checkout <commit ID>
, which will
move HEAD, a pointer to the tip of master (this was shown to us in the log as
HEAD -> master
, to the commit ID of our choice). I'll go back a few commits to
57d031d23
:
$ git checkout 57d031d23
Note: checking out '57d031d23'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 57d031d23... Merge pull request #13178 from anntzer/derole
$ git status
HEAD detached at 57d031d23
nothing to commit, working tree clean
With HEAD pointing to a commit farther back than the tip of master, we are in
Detached HEAD
state. This means we're pointing to a specific commit rather
than the tip of the branch. Performing a git log
here shows us all commits
previous to 57d031d23
, but none of the commits going forward.
$ git log -n 10 --oneline
57d031d23 (HEAD) Merge pull request #13178 from anntzer/derole
beed2d80e Merge pull request #13089 from anntzer/quivermatrix
aef686b43 Merge pull request #13179 from anntzer/axis_artist-deprecated
d9d3bdb49 Avoid calling a deprecated API in axis_artist.
bacea6a99 Remove :func: markup from mlab docstrings.
6b3c015da Merge pull request #13047 from timhoffm/doc-contourf-extend-cmap
d12be5098 Enable local doc building without git installation (#13015)
e1750a8e8 Don't try to find TeX-only fonts when layouting TeX text. (#13170)
a5988114c Merge pull request #12957 from Milania1/win-user-fonts
4cdd07189 Merge pull request #12951 from anntzer/get_layout
In this state we can look around, but we shouldn't make changes. If we do, our
changes going forward from 57d031d23
will not be associated with a branch, and
we won't be able to navigate back to them easily. To go back to our most recent
commit, we can type git checkout master
, which will return us to the tip of
our branch, master (more on branching later).
$ git checkout master
Previous HEAD position was 57d031d23... Merge pull request #13178 from anntzer/derole
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git log -n 2 --oneline
a552780fa (HEAD -> master, origin/master, origin/HEAD) Merge pull request #13107 from anntzer/bboxbase
a728b91c9 Merge pull request #13108 from anntzer/capitalize-docstrings
If you do happen to commit off of a detached head state, this page in the git book is a useful resource to make references out of these new commits: https://git-scm.com/docs/git-checkout#_detached_head
What if you have a series of large data files that you'd like to put into your
repository folder, but version controlling them isn't necessary?
We can ignore
files and entire folders from being tracked by git. Let's say I get a data file
called mydata.h5
and I want to ignore it. This is the series of commands that
I'd execute to make that happen.
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
mydata.h5
nothing added to commit but untracked files present (use "git add" to track)
$ vi .gitignore
$ cat .gitignore
mydata.h5
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
Note that once I've modified my .gitignore to include mydata.h5
git will no
longer show it as an untracked file. But since I've created a new .gitignore
file that is something that I'll need to add and commit to my repository.
.gitingore files accept directories and wildcards to ignore entire subsets of files within the subdirectory structure of your repository.
$ cat .gitignore
*.zip
build/
mydata.h5
This particular .gitignore file will ignore all files ending in .zip, everything in the build folder, and a hdf5 data file called mydata.