(Re)generate: (find-git-intro)
Source code: (find-efunction 'find-git-intro)
More intros: (find-eev-quick-intro)
(find-eev-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
It is meant as both a tutorial and a sandbox.
Prerequisites: to run this you need bash, git, and gitk,
and you need to understand these topics well:
1. test blocks: http://anggtwu.net/eepitch.html
2. (find-pdf-like-intro "7. Shorter hyperlinks to PDF files")
The video is here:
Info: (find-1stclassvideo-links "2024git")
Play: (find-2024gitvideo "00:00")
LSubs: (find-2024gitlsubs "00:00")
Subs: http://anggtwu.net/2024-eev-git.html
Page: http://anggtwu.net/2023-eev-git.html
0. Introduction
This is a tutorial on Git with a free license:
John Wiegley: "Git from Bottom Up" (2009)
http://ftp.newartisans.com/pub/git.from.bottom.up.pdf
If you download it with `M-x brep',
(find-psne-intro "3. The new way: `M-x brep'")
then this index should work:
(code-pdf-page "gitfbu" "$S/http/ftp.newartisans.com/pub/git.from.bottom.up.pdf")
(code-pdf-text "gitfbu" "$S/http/ftp.newartisans.com/pub/git.from.bottom.up.pdf")
;; (find-gitfbupage)
;; (find-gitfbutext)
;; (find-gitfbupage 2 "1. License")
;; (find-gitfbupage 3 "2. Introduction")
;; (find-gitfbupage 5 "3. Repository: Directory content tracking")
;; (find-gitfbupage 6 "Introducing the blob")
;; (find-gitfbupage 7 "Blobs are stored in trees")
;; (find-gitfbupage 8 "How trees are made")
;; (find-gitfbupage 10 "The beauty of commits")
;; (find-gitfbupage 12 "A commit by any other name...")
;; (find-gitfbupage 15 "Branching and the power of rebase")
;; (find-gitfbupage 20 "4. The Index: Meet the middle man")
;; (find-gitfbupage 22 "Taking the index farther")
;; (find-gitfbupage 24 "5. To reset, or not to reset")
;; (find-gitfbupage 24 "Doing a mixed reset")
;; (find-gitfbupage 24 "Doing a soft reset")
;; (find-gitfbupage 25 "Doing a hard reset")
;; (find-gitfbupage 27 "6. Last links in the chain: Stashing and the reflog")
;; (find-gitfbupage 30 "7. Conclusion")
;; (find-gitfbupage 31 "8. Further reading")
And this is a document that comes with Git:
(find-man "7 gitrevisions" "illustration, by Jon Loeliger")
(find-gitdocfile "revisions.txt" "illustration, by Jon Loeliger")
https://git-scm.com/docs/gitrevisions
it has this figure:
G H I J
\ / \ /
D E F
\ | / \
\ | / |
\|/ |
B C
\ /
\ /
A
I will refer to it as "the Loeliger digram", and I will call
other figures like that "Loeliger diagrams".
All the texts on Git that I know use several different kinds of
diagrams - some very detailed, some less so - to explain the data
structures behind git repositories...
...and I don't know a single text on Git that contains precise
instructions for creating git repositories that correspond to
their diagrams! For example, how do we create a git repository
whose graph of commits has exactly the shape of the Loeliger
diagram above?
This intro will explain a way to create a git repository
corresponding to the Loelinger diagram above - and a lot more.
1. Preparation
Check that you have bash, git and gitk installed. Then run this:
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
mkdir -p $S/http/anggtwu.net/LATEX/
cd $S/http/anggtwu.net/LATEX/
wget -N 'http://anggtwu.net/LATEX/2023loeliger.pdf'
echo 'http://anggtwu.net/LATEX/2023loeliger.pdf' >> ~/.psne.log
mkdir -p $S/http/anggtwu.net/GIT/
cd $S/http/anggtwu.net/GIT/
wget -N 'http://anggtwu.net/GIT/eevgitlib1.sh'
echo 'http://anggtwu.net/GIT/eevgitlib1.sh' >> ~/.psne.log
cp -v $S/http/anggtwu.net/GIT/eevgitlib1.sh /tmp/
This will download local copies of this flipbook animation,
(code-pdf-page "loeliger" "$S/http/anggtwu.net/LATEX/2023loeliger.pdf")
(code-pdf-text "loeliger" "$S/http/anggtwu.net/LATEX/2023loeliger.pdf")
;; (find-loeligerpage)
;; (find-loeligertext)
and of eevgitlib1.sh, that is a library of bash functions with
test blocks. The "-N" tells wget to update the local copy if
the upstream one is never, and the cp at the end copies
eevgitlib1.sh to /tmp/.
We also need a way to point to anchors in eevgitlib1.sh using
short hyperlinks. Run this:
(code-c-d "eevgit" "$S/http/anggtwu.net/GIT/" :anchor)
;; (find-eevgitfile "eevgitlib1.sh")
2. A first test
Run this:
* (eepitch-bash)
* (eepitch-kill)
* (eepitch-bash)
rm -Rfv /tmp/eevgit-test1/
mkdir /tmp/eevgit-test1/
cd /tmp/eevgit-test1/
. /tmp/eevgitlib1.sh
MakeTree1
Diagram
# (find-gitk "/tmp/eevgit-test1/")
# (find-loeligerpage 30)
This will create a git repository whose tree of commits is
exactly the Loeliger diagram of the introduction, and then
display it in three ways. "Diagram" uses this,
git log --oneline --graph --decorate --all --date-order
and is defined here:
(find-eevgit "eevgitlib1.sh" "basic")
(find-eevgit "eevgitlib1.sh" "basic" "Diagram")
`find-gitk' uses gitk, and is defined here:
(find-eev "eev-plinks.el" "find-gitk")
and `find-loeligerpage' uses a diagram that was generated with
this program:
(find-angg "LUA/Loeliger1.lua")
Note that the eepitch block above is similar to the one in this
test block:
(find-eevgit "eevgitlib1.sh" "MakeTree1-test")
3. Timelines
Now try this test block:
(find-eevgit "eevgitlib1.sh" "Time-tests")
It runs the same git commands as the test in the previous
section, except that it has lots of commands like "T C3"
interspersed with the rest, and it has these commands at the end:
Timeline
Timeline | tee /tmp/all
Each "T C3" acts as a timestamp. It declares that we're at time
C3, and it "saves a low-resolution picture" of the git
repository into the file /tmp/eevgit_C3; then "Timeline"
combines all these low-resolution pictures into a single file.
Run the test block, then try:
(find-fline "/tmp/" "eevgit_C3")
(find-fline "/tmp/eevgit_C3")
(find-fline "/tmp/all" "Time: C3")
4. Magit
This eepitch block
* (eepitch-bash)
* (eepitch-kill)
* (eepitch-bash)
rm -Rfv /tmp/eevgit-test2/
mkdir /tmp/eevgit-test2/
cd /tmp/eevgit-test2/
cp -av $S/http/anggtwu.net/GIT/eevgitlib1.sh /tmp/
. /tmp/eevgitlib1.sh
git init
Modify file1; Dump; git add file1; Commit A
Modify file1; Dump; Commit B
Modify file1; Dump
cat file1
Diagram
# (find-gitk "/tmp/eevgit-test2/")
produces a simple git repository with an uncommited change - the
line "3" in the file "file1", that was added after the
"Commit B". If you've never used magit before, you can install
it by running the right sexps in the temporary buffer generated
by this,
(find-epackage-links 'magit)
and then you can run this,
(magit-status "/tmp/eevgit-test2/")
and learn the keys for staging changes and for creating a new
commit. Hints:
(code-c-d "magit" (ee-locate-library "magit") "magit" :gz)
(find-magitnode "Staging and Unstaging" "S" "magit-stage-modified")
(find-magitnode "Initiating a Commit" "c" "magit-commit")
5. Why 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 it - and even with that
most tests would be very hard to undo and to reproduce...
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
of the repository that I did not know how to undo - and after
spending some days trying to fix that I gave up, deleted that
repository, created a new one, and decided that I would always do
LOTS of local tests before messing up my public repository again.
This is the n-th version of my tools for "doing lots of local
tests" with git and magit. If you like this approach, please get
in contact! =)
6. Pushing and pulling
A typical use case for git is like this: there is a "shared"
git repository in a "server", and there are several
"developers", each on a different machine, who are working on
copies of the "shared" repository, and who are trying to
somehow synchronize their work. The eepitch block below simulates
that in a single machine:
* (eepitch-bash)
* (eepitch-kill)
* (eepitch-bash)
# Load the functions in eevgitlib1.sh
cp -av $S/http/anggtwu.net/GIT/eevgitlib1.sh /tmp/
. /tmp/eevgitlib1.sh
# Create a "shared" repository in /tmp/eevgit-repo-s/
rm -Rfv /tmp/eevgit-repo-s/
mkdir /tmp/eevgit-repo-s/
cd /tmp/eevgit-repo-s/
git init --bare
# Create a first "developer" repository in /tmp/eevgit-repo-1/
rm -Rfv /tmp/eevgit-repo-1/
mkdir /tmp/eevgit-repo-1/
cd /tmp/eevgit-repo-1/
git clone /tmp/eevgit-repo-s/ .
# The developer 1 creates the commits A and B and pushes them
Modify file1; git add file1; Commit A
Modify file1; Commit B
git push
# Create a second "developer" repository in /tmp/eevgit-repo-2/
rm -Rfv /tmp/eevgit-repo-2/
mkdir /tmp/eevgit-repo-2/
cd /tmp/eevgit-repo-2/
git clone /tmp/eevgit-repo-s/ .
# The developer 2 creates the commit C and pushes it
Modify file1; Commit C
git push
# The developer 1 pulls the commit C
cd /tmp/eevgit-repo-1/
git pull
TODO: explain how to do some of the operations above with magit
instead of with low-level git commands!
TODO: explain how to use `find-gitdoc-links' to point to the docs
that come with git! Example (Debian-centric):
(find-gitdoc-links "push")
# (find-gitk "/tmp/eevgit-repo-s/")
# (find-gitk "/tmp/eevgit-repo-1/")
# (find-gitk "/tmp/eevgit-repo-2/")
7. A historical note
The video below shows one of my previous attempts to create
reproducible tests for git. The interesting part starts at 0:20:
http://anggtwu.net/eev-videos/2020-doubt-about-merging.mp4
(code-eevvideo "merg" "2020-doubt-about-merging")
(find-mergvideo "0:00")
(find-mergvideo "0:20" "interesting part")
Note that the code is much harder to read than this,
(find-eevgit "eevgitlib1.sh" "Time-tests")
...that is arranged in columns and has timestamps.