Skip to content

Latest commit

 

History

History
401 lines (321 loc) · 14.5 KB

1.0-basics.md

File metadata and controls

401 lines (321 loc) · 14.5 KB

1.0 A quick review of git basics:

Covered commands:

  • git config
  • creating a repository with git init or git clone
  • git clone
  • git init
  • git add
  • git commit
  • git status
  • git log
  • git checkout

Setting up git

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 "[email protected]"

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] or git 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
  • 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 or git config -l

Creating a repository

  • 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.

Tracking Changes

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 area
  • git commit will save or commit our staged files to
  • git 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.

git cycle

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 <[email protected]>
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 with git commit --message or enter straight into a your preferred text editor with git 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 with git add -a

Exploring History

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 <[email protected]>
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 <[email protected]>
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

Ignoring Things

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.