Hi! My name is Eduardo Ochs, and the title of this
video is "Learning git with `try it!'s (and eev)".
I'm the author of an Emacs package called
eev, that most people find hard to
understand, but its tutorials have
lots of things to try, and
lots of examples, and when people start
running the examples they...
sometimes they feel that everything
makes sense. Whatever...
Let me start with a bit of
context. A few weeks ago, in December
of 2023, something broke in the scripts
that I use to update the
git repository of eev, and the parts
that kept the two branches of eev
in sync stopped working - and I had to
merge the two branches many times.
I'm very bad with merging... each merge
took me hours and put me in panic - I
was very afraid of doing wrong things
that I wouldn't be able to undo later...
by the way, I'm very bad with git...
and I'm good with programs that
let me do small reproducible tests...
preferably in REPLs.
A few years ago I tried to
create a way to learn git using REPLs and
reproducible tests, and I felt that it
was time to work on that again.
And by the way, about this figure here...
my presentation at the last EmacsConf, the
EmacsConf 2023, was called "REPLs in strange
places: Lua, LaTeX, LPeg, LPegRex and TikZ",
and this figure here is part of an
animation that I did using these
techniques, and TikZ...
and the full animation is here and
it shows how we can create a complex git
repository
with several
branches and with a merge here...
step by step. So, these things show
the names of the commits, the graph
of the commits, the branches, how
the branches move from one commit to
another one... the red dot here is the HEAD...
whatever. Anyway the focus of this
presentation is on the "try it!"s.
Let me run this thing here to
activate screenkey... so now people
can see the keys that I'm typing...
and let me show the "try it"s. Note that I
have eev installed, and I have this
indication here that eev-mode is active...
if we click on that with mouse-2 it
shows the main keys of eev...
let's go to this sandboxed tutorial,
that is the tutorial about git, that
is what I'm going to show today...
it lists some prerequisites
here, but whatever...
the introduction starts with
a mention of a tutorial on git
with a free license.
It suggests that we download this thing here
using brep, and
brep is explained
here... the idea is that we can put the
point here, type M-x brep, and then it
will show a temporary buffer with
a script for downloading a
temporary copy of this
PDF...
done. And and now we can execute
these two sexps here to define short
hyperlinks to that PDF...
let's take a look at that PDF... note
that it has several figures here... for
example, this figure here that
shows the HEAD, the circles are commit
objects, triangles are tree objects,
squares are blob objects...
and then it has diagrams with
another shape and other
conventions, then similar diagrams but
with a more complex structure... then
here's another thing... so several kinds of
diagrams, and here they even have colors!
Anyway, let me go back...
this is a diagram that is going
to be very important for us. This is a
diagram that appears in one
document that comes with git, it's called
gitrevisions... if I open this manpage
here, it is
here... note that this link here not only
opens this manpage but also searches
for this string in that manpage, so it
goes straight to the middle of the manpage...
and here the man page says: "here is
an illustration by John Loeliger" - and I'm going
to refer to this kind of diagram here as
a "Loeliger diagram". This is not the official
name, of course...
so this is THE Loeliger diagram -
for me it's the canonical example
of a Loeliger diagram... and
things that are similar to this one I
will also call them as Loeliger diagrams...
we saw... sorry...
we saw here how
this Loeliger diagram with the names
of the branches can
be created step by step, so this is the
the final Loeliger diagram of a certain git
repository, and the other Loeliger diagrams
show intermediate steps of how to create
a git repository with that structure.
And in this tutorial - in this
intro here, find-git-intro,
I will explain a way to create
a git repository corresponding to this
Loeliger diagram here, and a lot more.
Let me first show something
that doesn't have any prerequisites - I
mean, if you have eev installed then
you probably know how to turn on eev-mode,
which is this thing here... if eev-mode is
on
then
f8 is going to do this: it either sends
the current line to another Emacs buffer or
executes the current line if it starts
with a red star...
my example with no
prerequisites is in this page here...
so here we have an animation of how
that git repository can be constructed,
and we here we have this block here that
is an eepitch block. You can just copy...
we can just copy and paste this thing
here to an Emacs buffer,
and if
we execute this
thing these bullets here behave in
exactly the same way as the red stars, so
if I type f8 here three times it creates
a target buffer here running bash... note
that it says bash here, and it says bash
here... and now if I type f8 on the other
lines the lines will be sent to the
target buffer as if a user were
typing the lines one by one.
So here at the beginning I define
an environment variable called N and
several shell functions... and then here I
initialize a git repository and then I
give these commmands here.
Note that the commands... they
modify the file1 several times,
they have several "Commit"s, they create
new branches, they switch branches in
many points... and there's this obscure
command here, that merges two branches...
and if we execute this sexp
here it will show the result. The result
is in this directory here, /tmp/eevgit-test1/,
and this will run gitk
on that repository with certain
command-line options. It will show that
the contents of that repository is this...
this is the same tree as
before, but displayed in a
slightly messier way...
So, this was the first example -
one in which we just had to
copy this thing here to an Emacs buffer
and then execute this thing with f8s.
Now let's see the examples that are in...
in find-git-intro.
This section 1 shows some
preparations that we need to run.
We need to check that we have bash, git and
gitk installed, then we have to run
these things here just to make sure that
we have copies
of two files and that the
copies in this machine are the same
as the upstream copies...
after getting these two things
we can run these things here to access
the PDF with a flipbook animation -
in which each page is a frame of an
animation...
here - by the way, if you want to
understand what these things do
the trick is that you just have to duplicate
these lines and add a "find-" at the
beginning of each which function name here...
so instead of code-pdf-page and code-pdf-text
we will have find-code-pdf-page and
find-code-pdf-text, and if we execute
these things here... for example this
one... it will show us a temporary buffer
that
explains what this version here would do.
So this does something but does
not show us what it is doing, and
this explains what this thing here does.
We also need to run this thing
here to access
a local copy of my library of shell
functions... remember that here I defined
several shell functions and then I
used those shell functions
to create a certain git repository...
now this sexp here visits
that library of shell functions - it is
here... here we have an
index... here we have those shell
functions and a few others... here we have
basic tests that explain what are these
basic shell functions here...
and by the way, this thing here is something
that is very
interesting. It's something that I
call a "test block".
If I type M-x eeit
this will insert a test block at
the current point, and the syntax of the
test block depends on the
language that I'm using, so here
we are editing a shell script, and a test
block has this funny format here...
and this thing acts as a multi-line comment.
So for the shell this thing is a
multi-line comment, but for me this
thing is executable with f8s... if I put the
point here and type f8 several times it
runs some tests that sort of
explain these definitions here... so here
we have a section with basic commands
and the tests for these basic commands...
and then we have a section with this big
function here, MakeTree1, and then some
tests for MakeTree1...
this is this tree in an ugly format.
And note that in this test here
we created a tree with this
shape here, and now we have some extra
things here... these extra things here
are some examples of how to
query the data structures of that
repository. For example, if I ask git to
"show" what is the HEAD, in this case it
will show me that the HEAD is this thing
here... is a commit with this author, this
date, and so on... this message... and the
contents of the commit are this thing
here, that is being displayed as a diff
between the repository in a certain
moment and the repository in another
moment. If I run this thing here... if I ask
git to show what is the file1 in HEAD
it shows the file in another format
that is totally different... it's not a
diff it's just... it looks like a
normal file, not a diff. And I can also
run these things here to inspect all the
data structures...
and these things here in
comments are ways of accessing
the documentation of some things
that are here. So, for example I used
show-ref
here... the docs of git that come
with Debian come in many formats, so I
usually prefer to be able to choose
between all formats when I want to...
for example, to get more
information about show-ref
I can run this thing here, and it shows
me ways of accessing all these
formats - for example this thing here
opens the manpage converted to txt,
this thing here opens the manpage
itself, so it has boldface, underlined,
and so on... this thing here shows the
on page in
HTML...
and this thing
here asks git help to show me the
help about show-ref...
so here we have a big
shell function, and also an export...
and here we have the tests for this big
shell function, and some other
tests that I decided that this was the
best place to put them...
Note that
here we just saw how to run the tests
that are in this file here, in test
blocks... this test here in find-git-intro
is essentially the same thing as
before...
sorry, I deleted
this
thing... I had deleted the the
copy of eevgitlib1.sh in /tmp/, but now
these things are going to
work - I hope... yes.
So, it created that big tree...
it shows the tree in a certain
ugly format... now I can ask gitk to
display that tree in another ugly
format, but with more colors...
here it opens my flipbook
animation in the final page, that shows
the tree in another
format...
and so this explains the first
test... and note
that
this thing has several pages, and
the pages has some labels
here... what are these labels? Let me
explain that - because this is something
that I wrote a few days ago and I found
very interesting, very useful...
Let's go back to this file
here with my shell functions and
tests... note that here we have the
index, and at this moment the final
block
defines things about "Time" that are
commands for recording how a repository
changes through time, it has pointers to
the to the flipbook animation...
and the idea is that a
command like this one, Time 4:20, in a
script means "it's 4:20 now", or "at this
point of the script the timestamp
is
4:20"... or if we think on that as an
action, the action means: "take a low
resolution picture of the git repository
and save it in the file /tmp/eevgit_4:20"...
so, in this test here I will run
something very similar
to this big function here, that
created this tree here...
but now my new version of that...
let me open the old and and the new
versions side to side...
the new version has more columns,
and it has timestamps at many points...
for example, this point here is
going to be the timestamp A0, this is the
timestamp A1, timestamp A2, and so on...
so each one of these things takes a
low resolution picture of the repository
at that point... the low resolution picture
is just a tree
generated by git log...
and all these low resolution
pictures are saved to files with certain
names, and then at the end I can run
this thing here,
Timeline, that concatenates all these
files... so let's run that...
now if I run Timeline it generates
all these trees here, and this line here
does the same thing, but it
also generates a file called /tmp/all.
Now that we have that file we
can use that file to see how the
repository changes at each point... for
example, now we can understand
what happens when you create a new
commit, in the sense that some tags
are going to be moved to the new commit,
some tags are not going to be moved...
I found the rules very hard to
understand... I mean, when I was
able to draw the diagram then things
became much simpler, but just by
reading the rules and the manuals I
found them very complex, but... so, when I
started studying this diagram here the
the rules started to become clear to me,
and when I found a way to translate that
diagram to the other format, that is
much prettier, then things become much
clearer. So these diagrams helped me a lot.
So, this section here is about how to
create timelines, and how to inspect all
the files that were created... note that
here we have the individual files, and
then these files were concatenated into
this thing here, called "all"...
And here's one application.
Now that we have reproducible tests
it should be possible
to use these reproducible tests to create
a tutorial for
magit...
this eepitch block here creates a very
simple repository in /tmp/eevgit-test2/, and
this repository has two commits and then
I modify one of its files, file1,
and my shell functions do not
create a third commit.
And if we run magit on that repository...
by the way, if you do not have
magit installed then you can either
install it in the usual way or you can
use this thing here and install it in
the eev way... you may need this thing here
to configure MELPA,
like running this and this...
and then you can execute these
things here: package-initialize,
package-refresh-contents and package-install,
and then you will have magit in
your machine.
Anyway, I do have magit here.
Let me run this thing here... it runs magit
on that repository that I just created,
that has an uncommitted change.
Magit will say that we have unstaged changes,
then I can type uppercase S to stage
all these changes then I can type
lowercase c lowercase c to commit the
new change...
then magit will ask me to
write a commit message here... let me write
a very simple message, like Blah, here...
and then I can type C-x #
to save that commit...
and now it says that the HEAD is in
that commit here, whose message is Blah...
So I'm changing styles here. Up to
this point I was doing everything with
just shell commmands, and now I'm
using this thing here to create the
basis for learning, or for practicing,
magit commands...
so instead of creating a commit by
running "Commit C" or "Commit Blah"
I did that from magit, and it should be
possible to use that to create a
tutorial for magit that will explain some
operations that most people find difficult...
or anyway, or at least the
people like me find them difficult.
By the way, these are links to the
manual of
magit... this is the part that
explains how to use uppercase S to
stage changes, and this is a link to the
part that explains how to create new
commits... and again, I found these things
very hard to understand when I
started to learn magit...
and now here we have a section about
"Why this?", and about... anyway, let me
read this. I found git and magit both very
hard to learn. To test most concepts we
would need a repository with tags and
branches, and a second repository that
pulls from that...and even with that
most tests would be very hard to undo
and to reproduce...
and when I was trying to learn git...
more specifically, I was learning git
to set up a git repository
for eev, my package...
When I was trying to set up a git
repository for eev on GitHub for the
first time I did several things wrong on
the GitHub side, and I didn't know how to
fix that... I didn't know how to undo these
things... and after spending several
days trying to fix that I gave up, I
deleted that repository, I created a new
one, and I decided that I would be very
coward from that point on, because I
didn't know how to undo certain things...
and I decided I would always do lots
of local tests before messing up my
public repository again.
So at that point I started playing
with the idea of reproducible tests and
not committing everything to a
repository in GitHub, and this is my n-th
version of my tools for doing lots of
local tests. And, of course,
if you like this approach
then please get in contact!
Let me show another example of
something that the tutorials suppose
that... no, sorry, let me explain it
in another way. A typical use
case for git is like this: there's a
"shared" git repository in a "server",
and there are several "developers",
each one on a different
machine, and the developers are working
on copies of that shared repository, and
they are making changes on that and they are
trying to somehow synchronize their work.
So they are going to save
their changes to their local repositories,
and then they're going to push those
changes to the "server" somehow...
and I found that the
tutorials suppose that you are one
of the developers, and that you are
working with colleagues on that shared
repository... but I couldn't find easy
instructions for creating that
server repository, or for creating that
on a local machine... so this is my attempt
to fix that. This is a minimal version,
a miniature, of how to create the
server and the developer machines... and
instead of using several machines I just
use different directories in /tmp/.
So let me type f8 several times...
this first block here copies my
library to /tmp/ and loads the functions in
eevgitlib1.sh... this block here creates
a shared repository, that is going to
play the role of a server... the second
block creates a directory that will
play the role of the first
developer... in this block here
the Developer 1 creates two
commits and pushes them to the server...
so Commit A and Commit B, and then git
push... and now we create a second
directory, that will play the role of
a second
developer... so now we are going to have
three repositories, one ending with "s",
that plays the role of a server, one
that ends with "1", that plays the
rollers of the first developer, and
one that ends with "2", that plays the
role of the second developer...
and now here the second
developer creates a new commit, and
pushes that commit to that
repository... and that's a new commit
that the first developer
doesn't have yet, so now we switch to the
to the first developer... we just
switch to this directory here instead of
switching machines... and we run git pull.
So this is a miniature that
probably can be used - in the future,
say - to show how to do these things
with magit... I mean, we probably
can use that to teach people how
to do pulls and pushes with magit...
I haven't done that yet.
So, yeah, that's it for the moment!
So, a few ideas are already
implemented, we have some basic tests
here, all the "try it!"s should be very
easy to try...
but I only have one small section
about how to use that to teach magit.
To do things with magit we have to
create a
repository... preferably in a way in
which this creation mechanism is easy to
run again...
and then we have to teach people
what are the keys that they have to
press in magit... for example
here for staging the changes people
have to to press S in a certain part of
the magit buffer, and then they have to
type "c c" in another position of
the magit buffer... so it's a totally
different interface...
So: this is a prototype, but
again... if you like this approach,
please get in contact!
And... that's it! That's what we have
now.
Yeah, that's it. Bye! Thanks!