.git
..git
, we remove the repository and history (but keep the working directory!)..git
uses relative paths - you can move the whole thing somewhere else and it will still work$ git add somefile.txt
$ git commit
$ git add file.txt anotherfile.txt
$ git commit
git add
, we “stage” the change), then shoot (git commit
):All configuration we enter here ends up in ~/.gitconfig
.
First, the following commands will set your user name and email address:
$ git config --global user.name "Your Name"
$ git config --global user.email yourname@example.com
The name and contact email will be recorded together with the code changes when we run git commit
.
If you’re using GitHub, and if you’d like to keep your personal email address private, you can use a GitHub-provided no-reply email address as your commit email address. See here for further details.
It is convenient to set also the default text editor to use with Git. This you do with (You can replace nano with vim, emacs, or any other editor of your choice.):
$ git config --global core.editor nano
We will learn how to initialize a Git repository, how to track changes, and how to make delicious guacamole!
This example is inspired by Byron Smith, for original reference, see this thread. The motivation for taking a cooking recipe instead of a program is that everybody can relate to cooking but not everybody may be able to relate to a program written in e.g. Python or another language.
Let us start. One of the basic principles of Git is that it is easy to create repositories:
$ mkdir recipe
$ cd recipe
$ git init
That’s it! We have now created an empty Git repository.
We will use git status
a lot to check out what is going on:
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
We will make sense of this information during this morning.
Let us now create two files.
One file is called instructions.txt
and contains:
* chop avocados
* chop onion
* squeeze lime
* add salt
* and mix well
The second file is called ingredients.txt
and contains:
* 2 avocados
* 1 lime
* 2 tsp salt
As mentioned above, in Git you can always check the status of files in your repository using
git status
. It is always a safe command to run and in general a good idea to
do when you are trying to figure out what to do next:
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
ingredients.txt
instructions.txt
nothing added to commit but untracked files present (use "git add" to track)
The two files are untracked in the repository (directory). You want to add the files (focus the camera) to the list of files tracked by Git. Git does not track any files automatically and you need make a conscious decision to add a file. Let’s do what Git hints at and add the files:
$ git add ingredients.txt
$ git add instructions.txt
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: ingredients.txt
new file: instructions.txt
Now this change is staged and ready to be committed.
Let us now commit the change to the repository:
$ git commit -m "adding ingredients and instructions"
[master (root-commit) aa243ea] adding ingredients and instructions
2 files changed, 8 insertions(+)
create mode 100644 ingredients.txt
create mode 100644 instructions.txt
Right after we query the status to get this useful command into our muscle memory:
$ git status
What does the -m
flag mean? Let us check the help page for that command:
$ git help commit
You should see a very long help page as the tool is very versatile. Do not worry about this now but keep in mind that you can always read the help files when in doubt. Searching online can also be useful, but choosing search terms to find relevant information takes some practice and discussions in some online threads may be confusing. Note that help pages also work when you don’t have a network connection!
Now try git log
:
$ git log
commit d619bf848a3f83f05e8c08c7f4dcda3490cd99d9
Author: Radovan Bast <bast@users.noreply.github.com>
Date: Thu May 4 15:02:56 2017 +0200
adding ingredients and instructions
git log --oneline
only shows the first 7 characters of the commit hash and is good to get an overview.git log --stat
is nice to show which files have been modified.Add 1/2 onion to ingredients.txt
and also the instruction
to “enjoy!” to instructions.txt
. Do not stage the changes yet.
When you are done editing the files, try git diff
:
$ git diff
diff --git a/ingredients.txt b/ingredients.txt
index 2607525..ec0abc6 100644
--- a/ingredients.txt
+++ b/ingredients.txt
@@ -1,3 +1,4 @@
* 2 avocados
* 1 lime
* 2 tsp salt
+* 1/2 onion
diff --git a/instructions.txt b/instructions.txt
index 6a8b2af..f7dd63a 100644
--- a/instructions.txt
+++ b/instructions.txt
@@ -3,3 +3,4 @@
* squeeze lime
* add salt
* and mix well
+* enjoy!
Now first stage and commit each change separately (what happens when we leave out the -m
flag?):
$ git add ingredients.txt
$ git commit -m "add half an onion"
$ git add instructions.txt
$ git commit # <-- we have left out -m "..."
When you leave out the -m
flag, Git should open an editor where you can edit
your commit message. This message will be associated and stored with the
changes you made. This message is your chance to explain what you’ve done and
convince others (and your future self) that the changes you made were
justified. Write a message and save and close the file.
When you are done committing the changes, experiment with these commands:
$ git log # show commit logs
$ git show # show various types of objects
$ git diff # show changes
Using git log --oneline
we understand that the first line of the commit message is very important.
Good example:
increase threshold alpha to 2.0
the motivation for this change is
to enable ...
...
Convention: one line summarizing the commit, then one empty line, then paragraph(s) with more details in free form, if necessary.
git commit -v
(will show you the difference in the editor).git mv
(you will need to git commit
the rename).git log --oneline
and git status
.git diff <hash1> <hash2>
.git show <hash>
.git add -p
.git difftool
(requires installing one of the visual diff tools):$ git difftool
As a general rule compiled files are not committed to version control. There are many reasons for this:
For this we use .gitignore
files. Example:
# ignore compiled python 2 files
*.pyc
# ignore compiled python 3 files
__pycache__
.gitignore
uses something called a
shell glob syntax for
determining file patterns to ignore. You can read more about the syntax in the
documentation.
An example taken from documentation:
# ignore objects and archives, anywhere in the tree.
*.[oa]
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
# ignore everything under build directory
build/
You can have .gitignore
files in lower level directories and they affect the paths
relatively.
.gitignore
should be part of the repository (why?).
git status
a lot..gitignore
.We have seen how to make commits directly via the GitHub website, and also via command line. But it is also possible to work from within a Git graphical user interface (GUI):
Now we know how to save snapshots:
$ git add <file(s)>
$ git commit
And this is what we do as we program.
Every state is then saved and later we will learn how to go back to these “checkpoints” and how to undo things.
$ git init # initialize new repository
$ git add # add files or stage file(s)
$ git commit # commit staged file(s)
$ git status # see what is going on
$ git log # see history
$ git diff # show unstaged/uncommitted modifications
$ git show # show the change for a specific commit
$ git mv # move tracked files
$ git rm # remove tracked files
Git is not ideal for large binary files (for this consider http://git-annex.branchable.com).
Initializing a Git repository is simple: git init
Commits should be used to tell a story.
Git uses the .git folder to store the snapshots.