(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.