Introduction to Git

Michael Jones

2024-07-03

Without Git

$ ls
my_project

Without Git

$ ls
my_project
my_project(2)

Without Git

$ ls
my_project
my_project(2)
my_project_v3

Without Git

$ ls
my_project
my_project(2)
my_project_v3
my_project_vfinal

Without Git

$ ls
my_project
my_project(2)
my_project_v3
my_project_vfinal
my_project_vfinal(2)

Without Git

$ ls
my_project
my_project(2)
my_project_v3
my_project_vfinal
my_project_vfinal(2)
my_project_final_final

Without Git

$ ls
my_project
my_project(2)
my_project_v3
my_project_vfinal
my_project_vfinal(2)
my_project_final_final
my_project_final_final_edit

Without Git

$ ls
my_project
my_project(2)
my_project_v3
my_project_vfinal
my_project_vfinal(2)
my_project_final_final
my_project_final_final_edit
my_project_when_will_it_end

Without Git

$ ls
my_project
my_project(2)
my_project_v3
my_project_vfinal
my_project_vfinal(2)
my_project_final_final
my_project_final_final_edit
my_project_when_will_it_end
my_project_when_will_it_end(2)

With Git

$ ls
my_project

With Git (showing hidden files)

$ ls
my_project
.git/

What does git give?

  • Tracking Changes
  • Time Travel
  • freedom to try alternatives
  • Working with others
  • Contribute to open source work

Concepts and
Key vocab

Concepts and key Vocab

  • repo : Collection of tracked files
  • Working directory : current state of files you’re working on
  • commit : snap shot of the working directory in time
  • diff : comparison of two files
  • branch : An alternative history

Concepts and key Vocab

  • git is the command, the tool, the protocol
  • GitHub is a website that uses git, but is separate
  • HEAD is a pointer to a specific commit. You working directory reflects whatever commit HEAD points to (plus and committed changes).

Concepts and key Vocab

  • remote : A copy of a repo somewhere else
  • clone : Get a copy of a repo onto your machine
  • pull : Get updates to that repo
  • push : Send your changes back

History is a Tree

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showCommitLabel': true}, 'themeVariables': {              'commitLabelFontSize': '32px'       } } }%%
gitGraph:
  commit id: "c1"
  commit id: "c2"
  commit id: "c3"
  branch feature
  commit id: "c4"
  commit id: "c5"
  checkout main
  merge feature

What can I track with git?

  • text files
  • binary files
  • really big files
  • but…

What should I not track?

It’s important to ask yourself whether you should track files. Generally don’t track compiled products of your other files (e.g. executable binaries or generated reports if they can be constructed from files you do track).

If you don’t want to track a file

Put the file name in .gitignore.

This is a file in the same location as .git.

Windows users, best do this through git bash on the CLI.

Getting Git

Windows

The easiest it git for windows, this comes with a suite of tools, including git bash and a basic GUI.

I strongly recommend diving into git bash. If you can program already, then using the command line is not a big deal, and the key git concepts map one-to-one with the commands. GUIs might speed you up later when you know how git works.

Mac

Probably Homebrew:

$ brew install git

Linux

Package manager

$ sudo apt install git

Or GUI.

With R

Install git

then

install.packages("usethis")
usethis::use_git()

in your projects.

Integration with RStudio.

Editors

  • Vim : tpope/fugitive
  • Emcas : Magit
  • VSCode : native git integration

how to

Git on The Command Line

There are many helpers for Git.

Some GUI tools.

CLI is best.

git init

Initialise your repo

$ git init
Initialized empty Git repository in /home/michael/git_example/.git/

Check your folder:

$ ls
 

Look closer:

$ ls -a
.  ..  .git

Do some work

Add a few files.

$ ls
file1.txt
file2.txt

Check git status

$ git status
On branch master

No commits yet

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

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

Stage your Commit

It’s like sending a parcel…

First you put items in a box.

Then you post the parcel.

Put the items in the box

$ git add file1.txt
$ git add file2.txt

Let’s check git status again.

$ git status
On branch master

No commits yet

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

Post the Parcel

$ git commit -m "add new files"
[master (root-commit) aaf330e] add new files
 2 files changed, 2 insertions(+)
 create mode 100644 file1.txt
 create mode 100644 file2.txt

Look at the log

Reminder git commit -m "add new files"

$ git log
commit aaf330e535dbe6319daee1a818ce627bc69ff3cf (HEAD -> master)
Author: Michael Jones <$EMAIL>
Date:   Tue Jul 2 21:56:41 2024 +0100

    add new files

Make some more changes

$ git diff
diff --git a/file1.txt b/file1.txt
index 7fbf76e..22824e8 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1 +1 @@
-This is the first file
+This is the second line of file 1

Send another parcel

$ git add file1.txt 

$ git commit -m "Update file1"
[master 9494c90] Update file1
 1 file changed, 1 insertion(+), 1 deletion(-)

Look at the log again

$ git log
commit 9494c90ac36176b758adaf9bd679a4da8a26c175 (HEAD -> master)
Author: Michael Jones <$EMAIL>
Date:   Tue Jul 2 22:03:32 2024 +0100

    Update file1

commit aaf330e535dbe6319daee1a818ce627bc69ff3cf
Author: Michael Jones <$EMAIL>
Date:   Tue Jul 2 21:56:41 2024 +0100

    add new files

Take a step back

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showCommitLabel': true}, 'themeVariables': {              'commitLabelFontSize': '16px'       } } }%%
gitGraph:
  commit id: "aaf330e"
  commit id: "9494c90"
$ git log --graph --oneline
* 9494c90 (HEAD -> master) Update file1
* aaf330e add new files

Working Loop

Write Code

Add files

Commit changes

Write Code

Add files

Commit changes

Working Loop (more realistic)

Write Code

git status

Add files

git status

Commit changes

git status

Write Code

Add files

git status

git log

Commit changes

Visit the past

$ git checkout HEAD~1
Note: switching to 'HEAD~1'.

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 switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at aaf330e add new files

Return to the present

$ git checkout master
Previous HEAD position was aaf330e add new files
Switched to branch 'master'

Let’s try something different

$ git branch feature

$ git checkout feature
Switched to branch 'feature'
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showCommitLabel': true}, 'themeVariables': {              'commitLabelFontSize': '16px'       } } }%%
gitGraph:
  commit id: "c1"
  commit id: "c2"
  branch feature
  checkout feature

Or in one go:

$ git checkout -b feature

Let’s try something different

(Do some work, and commit)

$ git add file1.txt 
$ git commit -m "changes file1 on feature branch"
[feature 59bb8e3] changes file1 on feature branch
 1 file changed, 1 insertion(+)
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showCommitLabel': true}, 'themeVariables': {              'commitLabelFontSize': '16px'       } } }%%
gitGraph:
  commit id: "c1"
  commit id: "c2"
  branch feature
  checkout feature
  commit id: "59bb8e3"

Get those changes back into master

$ git checkout master
Switched to branch 'master'

$ git merge feature
Updating 9494c90..59bb8e3
Fast-forward
 file1.txt | 1 +
 1 file changed, 1 insertion(+)
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showCommitLabel': true}, 'themeVariables': {              'commitLabelFontSize': '16px'       } } }%%
gitGraph:
  commit id: "c1"
  commit id: "c2"
  branch feature
  checkout feature
  commit id: "59bb8e3"
  checkout main
  merge feature

Realistic histories

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showCommitLabel': false}, 'themeVariables': {              'commitLabelFontSize': '16px'       } } }%%
gitGraph:
  commit
  commit
  commit
  branch feature
  checkout feature
  commit
  commit
  branch feature3
  checkout feature
  commit
  commit
  checkout main
  commit
  commit
  branch feature2
  checkout feature2
  commit
  commit
  checkout main
  merge feature
  checkout feature2
  merge main
  checkout main
  merge feature2
  checkout feature3
  commit

These might look more complicated

But they are built from the same actions we have already covered

Git Empowers you to work with others

Find a repo (GitHub, BitBucket, GitLab, etc)

git clone

Make a new branch

Make changes and commit

git push changes back up to the remote

git pull changes down

But Do Your Research First

Be comfortable branching

Be comfortable resolving merge conflicts

Write good commits and messages

Know what branching strategy the project uses

Open Source: Is there a CONTRIBUTIONS.MD file?

GitHub Features

Issues

Pull Requests

Social Aspect

Enterprise Aspects

Website Hosting

There’s plenty I’ve not shown

  • cherry-pick and rebase
  • git worktrees
  • git blame
  • specific git workflows when working with other people

Resources for learning

Resources for learning

Key Takeaways

Key Takeaways

  • Start small
  • work, git add, git commit, work, etc
  • It’s dauting, but there’s loads of help online
  • The best way to learn is to do: start contributing to open source projects or use git at work