ℹ️ Cette présentation est aussi disponible en français !
👩💻 Autonomous version (for solo reading)
A distributed Version Control System (VCS)
= 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!
Git ≠ GitHub, GitLab, Gitea, etc.
Git = software tool (command line)
GitHub and GitLab = Git repository hosting services
Linux ≠ OVH, for example
Benefits on several levels:
It's worth the trouble!
<section>
<p>Let's start with a parenthesis on the word “distributed”.</p>
<p class="fragment">You may have heard that Git is a <strong>distributed</strong> version control system .</p>
<p class="fragment">What does that mean??</p>
</section>
<section>
<h3>Two types of VCS</h3>
<dl>
<dt class="fragment">Centralised</dt>
<dd class="fragment">Any action on the repo requires access to the server <small class="fragment">(Subversion, Perforce, etc.)</small></dd>
<dt class="fragment">Distributed</dt>
<dd class="fragment">No copy of the repo is special <small class="fragment">(Mercurial, <strong>Git</strong>, etc.)</small></dd>
</dl>
</section>
<section>
<h3>Benefits of a distributed system</h3>
<ul>
<li class="fragment">Each developer has a full<sup aria-describedby="footnote-distributed">1</sup> copy of the repo, not just the server.<br/><strong class="fragment">➔ Yay, cheap backups!</strong></li>
<li class="fragment">Developers can work even offline!<br/><em class="fragment">(We will come back to conflict resolution later)</em></li>
</ul>
<small class="fragment" id="footnote-distributed"><sup>1</sup> For more details, watch <a href="https://www.youtube.com/watch?v=4XpnKHJAok8">this talk by Linus Torvalds at Google</a>.</small>
</section>
<section>
<h3 class="fragment">Let's cut to <del>the chase</del> graphs</h3>
<p class="fragment">❗️ <strong>I promise, nothing complicated!</strong> <small>(there will be plenty of images)</small></p>
<p class="fragment">Git is based on a <strong>graph</strong>.</p>
<aside class="notes">
<p>Well, time to get to the meat of the subject.</p>
<p>Git's choice for representing the various versions, is a <strong>graph</strong>.</p>
<p>This talk tries to make the different operations clearer, via animated visualisations!</p>
<p><small>Note: I am doubtful about the accessibility of the diagrams, unfortunately, but I don't know how to transcribe them either. If you use assistive technologies, <a href="https://eldred.fr/about#contact">please contact me</a>!</small></p>
</aside>
</section>
<section>
<h3>What is a <strong>commit</strong>?</h3>
<ul>
<li class="fragment" data-fragment-index="0">A commit message</li>
<li class="fragment" data-fragment-index="1">An author (name + email address)</li>
<li class="fragment" data-fragment-index="2">(Some other metadata...)</li>
<li class="fragment" data-fragment-index="3"><span class="fragment highlight-blue" data-fragment-index="5">A set of files and their contents</span></li>
<li class="fragment" data-fragment-index="4"><span class="fragment highlight-blue" data-fragment-index="6">“Arrows” towards its parent(s)</span></li>
</ul>
<p class="fragment">A commit is identified in an <strong>unique</strong> way by its <strong>hash</strong>.</p>
<aside class="notes">
<p>A term that you will see very often, and that is actually essential, is the <strong>commit</strong>.</p>
<p>Among all that constitutes a commit, what we are most interested in is the set of files it contains, and its family relationships.</p>
<p>All of this is, finally, summed up into a <strong>hash</strong>.</p>
</aside>
</section>
<section>
<h3>A hash? Is that edible?</h3>
<p class="fragment">All the information in a commit, <strong>including the contents of the files,</strong> are passed to a <strong>hashing</strong> function to obtain its <strong>hash</strong>.</p>
<p class="fragment">Principle of a hash function: data <small>(a sequence of bytes)</small> is passed to it, it returns a number (“hash”); two identical entries ⇔ two identical hashes.</p>
<small class="fragment">(More info for the curious <a href="https://en.wikipedia.org/wiki/Hash_function">on Wikipedia</a>)</small>
</section>
<section>
<h3>Commit hashes</h3>
<p class="fragment">The hash of a commit is a very large number, presented in <a href="https://en.wikipedia.org/wiki/Hexadecimal">hexadecimal</a>: <span class="fragment commit-id">6828f7bf493cd4c9c332ea769e6e38fbbe258821</span>.</p>
<p class="fragment">Hashes are often shortened (by default to 7 characters): <span class="commit-id">6828f7b</span>, this is what we will use throughout this course.</p>
</section>
<section>
<h3>“Pointers”</h3>
<p class="fragment" data-fragment-index="0">It's not just commits that point to commits.</p>
<svg viewBox="-5 -5 710 160" class="fragment" data-fragment-index="0">
<ellipse cx="45" cy="75" class="commit"/><text x="45" y="75" class="commit-id">f37c942</text>
<use x="90" y="75" href="#arrow-head"/><line x1="90" y1="75" x2="175" y2="75"/>
<ellipse cx="220" cy="75" class="commit"/><text x="220" y="75" class="commit-id">984b311</text>
<g class="fragment" data-fragment-index="3">
<use x="220" y="105" href="#arrow-head" transform="rotate(90,220,105)"/><line x1="220" y1="105" x2="220" y2="130"/>
<text x="220" y="140" class="tag centered">v1.7.10</text>
</g>
<use x="265" y="75" href="#arrow-head" transform="rotate(-33,265,75)"/><line x1="265" y1="75" x2="335" y2="30"/>
<ellipse cx="380" cy="30" class="commit"/><text x="380" y="30" class="commit-id">c4fe9cc</text>
<use x="425" y="30" href="#arrow-head"/><line x1="425" y1="30" x2="495" y2="30"/>
<ellipse cx="540" cy="30" class="commit"/><text x="540" y="30" class="commit-id">700aced</text>
<g class="fragment" data-fragment-index="2">
<use x="585" y="30" href="#arrow-head"/><line x1="585" y1="30" x2="635" y2="30"/>
<text x="640" y="30" class="branch">master</text>
</g>
<g class="fragment" data-fragment-index="4">
<use x="540" y="60" href="#arrow-head" transform="rotate(90,540,60)"/><line x1="540" y1="60" x2="540" y2="80"/>
<text x="540" y="90" class="head centered">HEAD</text>
</g>
<use x="265" y="75" href="#arrow-head" transform="rotate(33,265,75)"/><line x1="265" y1="75" x2="335" y2="120"/>
<ellipse cx="380" cy="120" class="commit"/><text x="380" y="120" class="commit-id">150dab6</text>
<g class="fragment" data-fragment-index="2">
<use x="425" y="120" href="#arrow-head"/><line x1="425" y1="120" x2="475" y2="120"/>
<text x="480" y="120" class="branch">network-fixes</text>
</g>
</svg>
<p class="fragment" data-fragment-index="1">There are also
<span class="fragment" data-fragment-index="2">branches,</span>
<span class="fragment" data-fragment-index="3">tags,</span>
<span class="fragment" data-fragment-index="4">and some other things.</span>
<small class="fragment" data-fragment-index="5">(We'll talk about their differences later)</small>
</p>
</section>
To create a commit...
... we simply add it to the graph.
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.
HEADHEAD 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”.
HEADAnd when creating a new commit?
HEAD follows the new commit (it is automatically checked out).
And when creating a new commit?
A branch follows the commit if and only if it is checked out.
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...)
Try to avoid graphic interfaces if possible.
(At least at the beginning.)
For example, their handling of errors is often problematic...
$ git init
Creates a new repository in the current directory.
Answer: the .git directory1.
1 In some cases it's a file.
Apparently there was an error?
Let's create a few files.
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.
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. GIT_EDITOR documentation in git-var.
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"
EDITOR in your .bashrc/.zshrc also works.# ...
export EDITOR=nano
# ...
<section>
<h3>Using a graphical editor</h3>
<p class="fragment">Yes, that's an option!</p>
<p class="fragment">It is however crucial to ensure that the command only returns when the file is closed:</p>
<dl style="display: block;">
<div class="fragment"><dt>Sublime Text</dt><dd>
$ git config --global core.editor "subl -w"
$ git config --global core.editor "code -w"
Git on your machine = backup tool (and more)
Git on many machines = 🤯
Each machine contains a Git repository. .git directory, etc.
Modifications can be “pushed” to another machine, and “pulled” from it as well.
git clonegit pullgit pushGit models remote machines using “remotes”.
A remote = a certain repo on a certain machine (more or less).
Remotes are managed via git remote!
git fetchGit does not make network requests for each command.
To remain up to date: git fetch <remote>.
(git pull implicitly calls git fetch.)
...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” a branch means “moving it only towards children commits”:
“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 mergegit rebaseAdvantages:
Downsides:
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
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)
git init
⚠️ Creates a repo in the current directory!
git clone <URL>
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 cleangit 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")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.confA 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
The slides are available online: https://eldred.fr/slides/git!
