Basic Git

2015-10-22

This is a tutorial I wrote for some colleagues to help them get started with using Git for version control.

Let’s work in a clean directory.

$ DIR=$(mktemp -d)
$ cd $DIR
$ pwd
/tmp/tmp.uXGAlR5aOL

git init

Start by setting up a Git repo.

$ git init
Initialized empty Git repository in /tmp/tmp.uXGAlR5aOL/.git/

A .git folder has been created:

$ ls -AF
.git/

$ ls -AF .git
branches/  config  description  HEAD  hooks/  info/  objects/  refs/

Let’s take some notes.

$ cat <<EOF > notes.txt
Notes for new project:

Write some cool code.

Write some useful documentation.
EOF

git status

To see which files have been added and changed in the repository:

$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    notes.txt

nothing added to commit but untracked files present (use "git add"
to track)

The new file can be added to the repo so that Git starts tracking changes to it:

$ git add notes.txt
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   notes.txt

git commit

Commit the addition of the file to the repo:

$ git commit -m 'First commit'
[master (root-commit) c9bbd04] First commit
 1 file changed, 5 insertions(+)
 create mode 100644 notes.txt

$ git status
On branch master
nothing to commit, working directory clean

Okay, to turn the notes into documentation, let’s do some formatting.

$ cat <<EOF > notes.txt
Notes for new project
=====================

Milestones
----------

* Write some cool code.
* Write some useful documentation.
EOF

The document is now in Markdown format, so it can easily be converted to HTML, PDF, DOCX, etc.

$ pandoc -t html notes.txt > notes.html

Here is notes.html:

<h1 id="notes-for-new-project">Notes for new project</h1>
<h2 id="milestones">Milestones</h2>
<ul>
<li>Write some cool code.</li>
<li>Write some useful documentation.</li>
</ul>

which renders in a browser as:

Notes for new project

Milestones

.gitignore

But since the HTML is auto-generated from the Markdown source, it doesn’t necessarily make sense to keep it under version control.

$ echo 'notes.html' > .gitignore
$ git add .gitignore

This tells Git to ignore notes.html.

(To ignore all HTML files, put “*.html” in .gitignore.)

$ git ls-files
.gitignore
notes.txt

git diff

To see the changes between the current files and the version in the latest commit:

$ git diff
diff --git a/notes.txt b/notes.txt
index 17d4cdb..15fd8e9 100644
--- a/notes.txt
+++ b/notes.txt
@@ -1,5 +1,8 @@
-Notes for new project:
+Notes for new project
+=====================

-Write some cool code.
+Milestones
+----------

-Write some useful documentation.
+* Write some cool code.
+* Write some useful documentation.

We can add all the changes to the staging area at once:

$ git add .
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

    new file:   .gitignore
    modified:   notes.txt

And do a new commit:

$ git commit -m 'Reformat docs' \
  -m 'Use markdown to enable easy conversion to other formats.' \
  -m 'HTML version not tracked because auto-generated from markdown.'
[master 7adf34e] Reformat docs
 2 files changed, 7 insertions(+), 3 deletions(-)
 create mode 100644 .gitignore

Or skip the --message option to open a text editor for entering the commit message—useful if the message is to be > 1 line long.

$ git commit
< $EDITOR is launched. Enter the text: >
Reformat docs

Use markdown to enable easy conversion to other formats.

HTML version not tracked because auto-generated from markdown.
< Save and quit. >

git log

Display the list of commits and their author:

$ git log
commit 7adf34eedfef8adc474223382be75e575268f3d7
Author: JA Viljoen <javiljoen@example.com>
Date:   Thu Oct 22 11:35:24 2015 +0200

    Reformat docs
    
    Use markdown to enable easy conversion to other formats.
    
    HTML version not tracked because auto-generated from markdown.

commit c9bbd045809e8e2d6a8d3016ed3c6fd060a9e24f
Author: JA Viljoen <javiljoen@example.com>
Date:   Thu Oct 22 11:35:17 2015 +0200

    First commit

There are various options to make the output more compact or fancy, e.g.

$ git log --oneline --decorate --color --graph
* 7adf34e (HEAD, master) Reformat docs
* c9bbd04 First commit

$ git log --color --graph
* commit 7adf34eedfef8adc474223382be75e575268f3d7
| Author: JA Viljoen <javiljoen@example.com>
| Date:   Thu Oct 22 11:35:24 2015 +0200
|
|     Reformat docs
|
|     Use markdown to enable easy conversion to other formats.
|
|     HTML version not tracked because auto-generated from markdown.
|
* commit c9bbd045809e8e2d6a8d3016ed3c6fd060a9e24f
  Author: JA Viljoen <javiljoen@example.com>
  Date:   Thu Oct 22 11:35:17 2015 +0200

      First commit

git rm/mv

To delete or rename a file in the repo, use the Git version of the commands.

$ git mv notes.{txt,md}
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    notes.txt -> notes.md

$ git commit -m 'Fix extension of markdown file'
[master 8c8c385] Fix extension of markdown file
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename notes.txt => notes.md (100%)

git tag

Tags can be used to mark “releases” or other significant versions.

$ git tag '0.1'

To list only the tagged commits, use --simplify-by-decoration:

$ git log --oneline --decorate
8c8c385 (HEAD, tag: 0.1, master) Fix extension of markdown file
7adf34e Reformat docs
c9bbd04 First commit

$ git log --oneline --decorate --simplify-by-decoration
8c8c385 (HEAD, tag: 0.1, master) Fix extension of markdown file
c9bbd04 First commit

git archive

To save a snapshot of the repo.

To archive the repo at its current state:

$ git archive -o repo.tar.gz HEAD
$ ls
notes.html  notes.md  repo.tar.gz

$ tar tf repo.tar.gz
.gitignore
notes.md

To archive it at a previous stage, use the commit identifier, e.g.:

$ COMMIT=$(git log --oneline | grep 'Reformat' | cut -f 1 -d' ')
$ echo $COMMIT
7adf34e

$ git archive -o repo.tar.gz $COMMIT
$ tar tf repo.tar.gz
.gitignore
notes.txt

Or use the tag of the commit:

$ git archive -o repo-0.1.tar.gz '0.1'
$ tar tf repo-0.1.tar.gz
.gitignore
notes.md

Deleting a repo

Since all Git’s records are contained in the .git subfolder, simply deleting the folder will delete all the contents and history of the repo.

$ cd
$ rm -rf $DIR