Becoming proficient with Git

ℹ️ Cette présentation est aussi disponible en français !

👩‍💻 Autonomous version (for solo reading)

What is Git?

A distributed Version Control System (VCS)

Version control system

= system allowing to manage different versions of a set of files

(Many intermediate versions between two releases!)

Often used to allow several people work the same on code... among other reasons!

Other VCS

  • Subversion (SVN)
  • Perforce (p4)
  • CVS
  • Mercurial
  • Bazaar

What Git is not

Git ≠ GitHub, GitLab, Gitea, etc.

Git = software tool (command line)

GitHub and GitLab = Git repository hosting services

Linux ≠ OVH, for example

Why use Git?

Benefits on several levels:

  1. Backup system
  2. Work in “branches”
  3. Collaborative work

It's worth the trouble!

Making backups with Git

Let's start with a parenthesis on the word “distributed”.

You may have heard that Git is a distributed version control system .

What does that mean??

Two types of VCS

Centralised
Any action on the repo requires access to the server (Subversion, Perforce, etc.)
Distributed
No copy of the repo is special (Mercurial, Git, etc.)

Benefits of a distributed system

  • Each developer has a full1 copy of the repo, not just the server.
    ➔ Yay, cheap backups!
  • Developers can work even offline!
    (We will come back to conflict resolution later)
1 For more details, watch this talk by Linus Torvalds at Google.

Basic concepts

Let's cut to the chase graphs

❗️ I promise, nothing complicated! (there will be plenty of images)

Git is based on a graph.

What is a commit?

  • A commit message
  • An author (name + email address)
  • (Some other metadata...)
  • A set of files and their contents
  • “Arrows” towards its parent(s)

A commit is identified in an unique way by its hash.

A hash? Is that edible?

All the information in a commit, including the contents of the files, are passed to a hashing function to obtain its hash.

Principle of a hash function: data (a sequence of bytes) is passed to it, it returns a number (“hash”); two identical entries ⇔ two identical hashes.

(More info for the curious on Wikipedia)

Commit hashes

The hash of a commit is a very large number, presented in hexadecimal: 6828f7bf493cd4c9c332ea769e6e38fbbe258821.

Hashes are often shortened (by default to 7 characters): 6828f7b, this is what we will use throughout this course.

“Pointers”

It's not just commits that point to commits.

f37c942 984b311 v1.7.10 c4fe9cc 700aced master HEAD 150dab6 network-fixes

There are also branches, tags, and some other things. (We'll talk about their differences later)

Manipulating the graph

Creating a commit

f37c942 984b311 c4fe9cc

To create a commit...

... we simply add it to the graph.

That's all!

There is no trick here, (almost) all operations only ever add commits to the graph.

Though, let's talk about what happens when we do.

HEAD

HEAD refers to the commit that is currently checked out.

That is, it is the commit whose contents (files) are currently present in the directory.

The commit pointed to by HEAD can be thought of as “where we are right now”.

HEAD

And when creating a new commit?

f37c942 984b311 HEAD c4fe9cc HEAD

HEAD follows the new commit (it is automatically checked out).

Branches

And when creating a new commit?

f37c942 master 984b311 develop crash-fix HEAD c4fe9cc crash-fix HEAD

A branch follows the commit if and only if it is checked out.

Tags

A tag is immovable and cannot be checked out, so it never follows a new commit.

(To “move” a tag, it must be deleted and re-created elsewhere.)

➔ A branch is used to follow something (development of a feature...); a tag is used to mark a particular commit (version...)

Let's talk commands

Try to avoid graphic interfaces if possible.

(At least at the beginning.)

For example, their handling of errors is often problematic...

Create a new Git repository

		$ git init

Creates a new repository in the current directory.

What makes up a Git repository?

Answer: the .git directory1.

  • Git doesn't store anything outside of that directory.
  • Its parent directory can be freely moved, Git stores no absolute paths.
  • Git also looks for it in every parent directory of the current directory.

1 In some cases it's a file.

Creating a commit

Apparently there was an error?

Let's create a few files.

“Where am I?”

Let's talk staging

I promise this is the last thing

Git lets you choose which modifications will be recorded in the next commit.

This is done via the git add command suggested by the earlier hint text.

Interactive editor

We just witnessed git commit opening a text editor.

Text editor for use by Git commands. The value is meant to be interpreted by the shell when it is used. Examples: ~/bin/vi, $SOME_ENVIRONMENT_VARIABLE, "C:\Program Files\Vim\gvim.exe" --nofork. The order of preference is the $GIT_EDITOR environment variable, then core.editor configuration, then $VISUAL, then $EDITOR, and then the default chosen at compile time, which is usually vi.
Source: GIT_EDITOR documentation in git-var.

Changing the configuration

The editor used by default is vi, which has a... peculiar ergonomy.

To change that to nano (for example):

			$ git config --global core.editor "nano"
Setting EDITOR in your .bashrc/.zshrc also works.
				# ...
				export EDITOR=nano
				# ...

Using a graphical editor

Yes, that's an option!

It is however crucial to ensure that the command only returns when the file is closed:

Sublime Text
$ git config --global core.editor "subl -w"
VS Code
$ git config --global core.editor "code -w"

Collaboration

Git on your machine = backup tool (and more)

Git on many machines = 🤯

Principle

Each machine contains a Git repository. .git directory, etc.

Modifications can be “pushed” to another machine, and “pulled” from it as well.

origin 6846ef5 master ac2b311 1234567 master 3d5f4a2 master tsfe01 $ git init $ git commit $ git push $ git pull $ git commit $ git push 6846ef5 master ac2b311 1234567 master 3d5f4a2 master tsfe02 $ git clone $ git commit $ git commit $ git push 6846ef5 master ac2b311 master 1234567 master

Summary

  • To create a local copy of a remote repo: git clone
  • To retrieve updates from a remote repo: git pull
  • To publish my modifications to a remote copy: git push

Some more terminology

Git models remote machines using “remotes”.

A remote = a certain repo on a certain machine (more or less).

Remotes are managed via git remote!

Remotes & refs

origin ac2b311 master 6846ef5 develop tsfe01 6846ef5 develop 06adada fix-tests tsfe02 ac2b311 develop 24a8c81 lts-fixes develop origin/develop tsfe02/develop

git fetch

Git does not make network requests for each command.

  • Saves bandwidth
  • Allows working offline

To remain up to date: git fetch <remote>.

(git pull implicitly calls git fetch.)

Collaboration (2)

When things go wrong

origin 6846ef5 master ac2b311 master tsfe01 $ git commit $ git push ? 6846ef5 master 06adada master tsfe02 $ git commit $ git push 6846ef5 master ac2b311 master

When things go wrong...

...Git has our backs.

issotm@sheik-kitty /tmp/test% git push
To example.com:path/to/repo.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'example.com:path/to/repo.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

... “non-fast-forward”?

Fast-forwarding

“Fast-forwarding” a branch means “moving it only towards children commits”:

6846ef5 ac2b311 master 1234567 06adada 3d5f4a2 feedfac master master master master master

Fast-forwarding

“Fast-forwarding” because it's only ever going “forward” in time.

Fast-forward = always safe (can't “lose” any commits).

...what about non-fast-forward cases?

  • git merge
  • git rebase

Merge

Principle

6846ef5 ac2b311 1234567 master 06adada add-dark-mode 3d5f4a2 add-dark-mode feedfac

Advantages:

  • History preserved

Downsides:

  • Non-linear master
  • “Merge commits” are artificial

Command

git merge <commit>...

Creates a new commit on the current branch that “gathers” the current branch and all <commit>s.

We will explain the “gather”ing together with rebase.

Example: git merge master

Rebase

Principle

6846ef5 ac2b311 1234567 master 06adada 3d5f4a2 add-dark-mode 14e684a af58e36 add-dark-mode

Command

git rebase <new-base> [<branch>]

If <branch> is omitted, the current branch is modified.

Example: git rebase master (or git rebase master add-dark-mode)

Quick recap

Create a new repo

git init

⚠️ Creates a repo in the current directory!

Create a local copy of a repo

git clone <URL>

Finding ourselves

git status

issotm@sheik-kitty /tmp/rgbds% git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Finding ourselves

git status

issotm@sheik-kitty /tmp/rgbds% git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   .editorconfig
        deleted:    .checkpatch.conf

no changes added to commit (use "git add" and/or "git commit -a")

Select modifications to commit

git add


issotm@sheik-kitty /tmp/rgbds% git add .editorconfig
issotm@sheik-kitty /tmp/rgbds% git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   .editorconfig

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    .checkpatch.conf

Goodies

A neater visualiser for git diff and git blame : delta

The Git status can be shown in the shell prompt (for example via powerlevel10k)

A good graphical interface (though freeware): Sublime Merge (I recommend because it shows the commands it executes)

If you use an IDE, it may have a Git integration (sometimes via extensions), read the docs

Thank you for following!

The slides are available online: https://eldred.fr/slides/git!