commit fe27c35fc492bb1d4cca0f5d9f11367d46303937 Author: Éibhear Ó hAnluain Date: Tue Jun 26 09:03:58 2018 +0100 Initial basis diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d446f5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +simpleRepo +largeFileRepo +devTeamDemo diff --git a/GitDeepDive.org b/GitDeepDive.org new file mode 100644 index 0000000..a3d1073 --- /dev/null +++ b/GitDeepDive.org @@ -0,0 +1,27 @@ + +* Git Deep Dive + A Version 1 Technical Meetup talk covering the deep internals of git. + +** Introduction + This is the slide-deck and set-up scripts used to give the /Git + Deep Dive/ technical meet-up talk on [2018-06-25 Mon] in Version 1, + by Éibhear Ó hAnluain. + + The pack comes with the following: + - This document + - The slide-deck, =GitDeepDive.pdf= + - A script to set up a simple git repository for exploration + purposes: =merge-setup.sh= + - A script to set up the mimic of a development team and processes: + =gitDemo.sh= + - A script to set up another simple repository to run through the + process for completely clearing a file out of a git database: + =largeFile-setup.sh=. + - A =.gitignore= file. + +** Setup + 1) Run the script =merge-setup.sh=. This will create a git + repository in =simpleRepo= and populate it with some + commits. The commits in this repository will correspond to the + diagrams in the slide-deck that relate to merging. + 2) diff --git a/GitDeepDive.pdf b/GitDeepDive.pdf new file mode 100644 index 0000000..536bd9f Binary files /dev/null and b/GitDeepDive.pdf differ diff --git a/commands.txt b/commands.txt new file mode 100644 index 0000000..8bd6d0d --- /dev/null +++ b/commands.txt @@ -0,0 +1,201 @@ + +Setup + bash ~/eibhear_org/scripts/gitDemo.sh + bash ~/eibhear_org/Version1/TechTalks/merge-setup.sh + gpg2 --generate-key + git config --global gpg.program gpg2 + +Slide: Configuration + git config --list + cd ~/tmp/DeepDive1 + git config --local --list + git config --global --list + git config --system --list + git config --global user.name "Éibhear Ó hAnluain" + git config --global user.email "eibhear.ohanluain@version1.com" + git config -e + # Slide + +Slide: fetch and merge, not pull + cd ~/tmp/gitDemo/javaBootcampNoEclipse.dev1 + git fetch --prune + # Slide + git branch -va + # Slide + +Slide: Merging approaches: fast-forward + cd ~/tmp/DeepDive1 + git checkout master + git log --decorate --graph --oneline --all + git merge Rel1 + # Slide + git log --decorate --graph --oneline --all + # Slide + +Slide: Merging approaches: merging strategies + cd ~/tmp/DeepDive1 + git checkout master + git merge Rel2 + git log --decorate --graph --oneline --all + # Slide + +Slide: Merging approaches: Rebase + bash ~/eibhear_org/Version1/TechTalks/merge-setup.sh + cd ~/tmp/DeepDive1 + git checkout master + git log --decorate --graph --oneline --all + git merge Rel1 + git log --decorate --graph --oneline --all + git checkout Rel2 + git rebase master + # Slide + git log --decorate --graph --oneline --all + # Slide + +Slide: refs + bash ~/eibhear_org/Version1/TechTalks/merge-setup.sh + cd ~/tmp/DeepDive1 + + ls -l .git/refs/heads/ + cat .git/refs/heads/Rel2 + # Slide + + git tag Rel1.0 Rel1 + cat .git/refs/heads/Rel1 + cat .git/refs/tags/Rel1.0 + + cat .git/HEAD + # Slide + + cd ~/tmp/gitDemo/javaBootcampNoEclipse.dev1 + ls -l .git/refs/remotes/origin/ + cat .git/packed-refs + # Slide + +Slide: Annotated tags + cd ~/tmp/DeepDive1 + cat .git/refs/tags/Rel1.0 + git cat-file -t $(cat .git/refs/tags/Rel1.0) + git cat-file -p $(cat .git/refs/tags/Rel1.0) + # Slide + + git tag -a -m "Formal release of 1.0" Rel1.0.prod Rel1 + cat .git/refs/tags/Rel1.0.prod + git cat-file -t $(cat .git/refs/tags/Rel1.0.prod) + git cat-file -p $(cat .git/refs/tags/Rel1.0.prod) + # Slide + +Slide: blame + git blame information.md + git checkout Rel1 + git blame information.md + git merge Rel2 + git blame information.md + # Slide + +Slide: Tag and commit signing + gpg --list-secret-keys + git checkout master + # Edit information.md + git commit -a -Seibhear.ohanluain@version1.com -m "Update to information.md" + git cat-file -p master + git tag -s -u eibhear.ohanluain@version1.com -m "Release 2." Rel2.0 Rel2 + git cat-file -p Rel2.0 + # Slide + + git tag -v Rel2.0 + git log --show-signature -1 + # Slide + +Slide: Git Objects -- blobs + cat ~/.bash_history | git hash-object --stdin + # Slide + +Slide: Git Objects -- trees + cd ~/tmp/gitDemo/javaBootcampNoEclipse.dev1 + cat .git/refs/heads/master + git cat-file -p + # Slide + +Slide: Git Objects -- commits + cd ~/tmp/DeepDive1 + git log --graph --all --decorate --oneline + git cat-file -p HEAD + git cat-file -p + # Slide + +Slide: Git Objects -- tags + git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize)' --batch-all-objects | grep tag + git cat-file -p + # Slide + +Slide: "Content Addressable Filesystem" + git rev-list --all --objects + git cat-file -p + git cat-file -p | git hash-object --stdin + ls -l .git/objects/... + # Slide + +Slide: The reflog + git reflog + git reflog expire --expire=now --expire-unreachable=now --verbose --all + git reflog + # Slide + +Slide: fsck and gc + git fsck + git gc + # Slide + +Slide: Useful commands + bash ~/eibhear_org/Version1/TechTalks/largeFile-setup.sh + cd ~/tmp/DeepDive1 + git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize)' --batch-all-objects | sed -n 's/^blob //p' | sort -n --key=2 + git rev-list --objects --all | grep + git log --follow -- "largeInformation.md" + # Slide + +Slide: Permanently removing a file from your git db [1/2] + for tag in $(git tag) + do + echo "${tag},$(git log --format="%H,\"%cn\",\"%ci\",\"%s\"" ${tag} | head -1)" + done | tee ../tag_list.csv + for branch in $(git branch -r | grep -v HEAD | sed 's/\ \ origin\///') + do + git checkout ${branch} + done + for branch in $(git branch | sed 's/^..//') + do + git checkout -q ${branch} + du -sk . | sed "s/\./${branch}/" + done | tee ../branch_sizes.out + # Slide + git checkout Rel1 + # Slide + git filter-branch --tree-filter 'rm -f largeInformation.md' --prune-empty HEAD + # Slide + git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d + # Slide + for branch in Rel2 Rel3 Rel4 master + do + git checkout ${branch} + git filter-branch --tree-filter 'rm -f largeInformation.md' --prune-empty HEAD + git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d + done | tee ../cleanup.out + # Slide + git reflog expire --expire-unreachable=now --all + # Slide + git gc --prune=now + # Slide + git fsck --unreachable --no-reflogs + # Slide + for branch in $(git branch | sed 's/^..//') + do + git checkout -q ${branch} + du -sk . | sed "s/\./${branch}/" + done | tee ../branch_sizes_post_process.out + # Slide + + +# End + diff --git a/gitDemo.sh b/gitDemo.sh new file mode 100644 index 0000000..1398767 --- /dev/null +++ b/gitDemo.sh @@ -0,0 +1,6383 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd $(dirname ${0}); pwd) +BASEDIR=${SCRIPT_DIR}/devTeamDemo + +declaim () { + echo + echo ${*} + echo "===============" + echo +} + +usage () { + declaim "${0} [-s]" +} + +sleepies () { + if [ "${SLEEPS}" = "Y" ]; then + sleep ${1} + fi +} + +# We expect the group, project and branch as parameters +export SLEEPS="N" +while getopts "sh" opt; do + case ${opt} in + s) # We answer "Yes" to all questions + SLEEPS="Y" + ;; + h) # We want to know how this works. + usage + exit 0 + ;; + *) usage + exit 1 + ;; + esac +done +# shift to the first non-option parameter. +shift $(( ${OPTIND} - 1 )); unset OPTIND + +declaim "Preparing..." +cd +rm -rf ${BASEDIR} +mkdir -pv ${BASEDIR} +cd ${BASEDIR} + +declaim "Initialising 'remote' git repository" +# Create my sample git project +cat < +

+- Bean example: <%= MyHelloWorld.getStrMyMessage() %>. ++ Bean example: <%= MyHelloWorld.getStrMyMessage() %>. +

+

+- The text in bold is the output of a call ++ The text in underline is the output of a call + to MyHelloWorld.getStrMyMessage(). +

+ +EOF +git add source +git commit -m "Formatting changes." +git push + +sleepies 15 + +# Master creates a release branch +declaim "Master creates another release branch" +cd ${BASEDIR}/javaBootcampNoEclipse.mastersClone +git checkout REL2018.11 +git pull --prune origin +git checkout master +git pull --prune origin +git branch REL2019.02 master +git push origin REL2019.02 + +sleepies 15 + +# Developer 1 develops for the later release +declaim "Developer 1 develops for the second release branch" +cd ${BASEDIR}/javaBootcampNoEclipse.dev1 + +git fetch --prune +git checkout REL2019.02 +git branch REL2019.02_dev1 +git checkout REL2019.02_dev1 +git push --set-upstream origin REL2019.02_dev1 + +sleepies 15 + +cat -v <"); + out.println(""); +EOF +git add source +git commit -m "Further variablisation." +git push + +sleepies 15 + +# Master prepares to merge development work to first release branch +declaim "Master prepares for merge requests" +cd ${BASEDIR}/javaBootcampNoEclipse.mastersClone +git checkout master +git fetch --prune +for branch in $(git branch -l | grep -v master) +do + git branch -D ${branch} +done +for branch in $(git branch -r | grep -v HEAD | sed 's/^\ \ origin\///') +do + git branch ${branch} origin/${branch} +done +git checkout master + +# Master does the merge +declaim "Master merges Developer 1 and Developer 2's work for first release" +git checkout REL2018.11 +git merge --no-ff -m "Merge REL2018.11_dev1 following approved code-review" REL2018.11_dev1 +git merge --no-ff -m "Merge REL2018.11_dev2 following approved code-review" REL2018.11_dev2 +git push origin + +sleepies 15 + +# Developer 1 merges the new merge into their own branch +declaim "Developer 1 updates their working area following the merge" +cd ${BASEDIR}/javaBootcampNoEclipse.dev1 +git fetch --prune +git checkout REL2018.11_dev1 +git pull origin REL2018.11 +git push origin + +sleepies 15 + +# Developer 2 merges the new merge into their own branch +declaim "Developer 2 updates their working area following the merge" +cd ${BASEDIR}/javaBootcampNoEclipse.dev2 +git fetch --prune +git checkout REL2018.11_dev2 +git pull origin REL2018.11 +git push origin + +sleepies 15 + +# Developer 1 develops for the first release +declaim "Developer 1 makes an update for the first release" +cd ${BASEDIR}/javaBootcampNoEclipse.dev1 + +git fetch --prune +git checkout REL2018.11_dev1 + +cat -v < information_compressed.out + +counter=0 +while [ ${counter} -lt 15 ]; +do + cat information_compressed.out information_compressed.out > information_compressed2.out + mv information_compressed2.out information_compressed.out + counter=$(( $counter + 1 )) +done +mv information_compressed.out largeInformation.md + +declaim "Adding and commiting that new file" +git add largeInformation.md +git commit -m "A large, awkwardly binary file" + +declaim "Creating and checking out the Rel3 branch" +git checkout -b Rel3 + +declaim "Modifying the large binary file on Rel3" +cat information.md information.md information.md >> largeInformation.md + +declaim "Adding and commiting that change to the binary file." +git add largeInformation.md +git commit -m "Changes to that large file" + +declaim "Creating and checking out the Rel4 branch" +git checkout master +git checkout -b Rel4 + +declaim "Modifying the large binary file on Rel4" +cat largeInformation.md largeInformation.md > largeInformation2.md +rm largeInformation.md +mv largeInformation{2,}.md + +declaim "Adding and commiting that change to the binary file." +git add largeInformation.md +git commit -m "An even larger file" + +declaim "Merging Rel3 and Rel4 into master" +git checkout master +git merge Rel3 +git merge -s recursive -Xtheirs -m "Merge of Rel4 into master" Rel4 + +declaim "Removing that large file, now." +git rm largeInformation.md +git commit -m "large binary file gone again" + +git log --oneline --graph --decorate --all + +declaim "Repository size in kibibytes: $(du -sk .)" diff --git a/merge-setup.sh b/merge-setup.sh new file mode 100644 index 0000000..9860b5c --- /dev/null +++ b/merge-setup.sh @@ -0,0 +1,117 @@ +#!/bin/bash + +declaim () { + echo + echo ${*} + echo "===============" + echo +} + +SCRIPT_DIR=$(cd $(dirname ${0}); pwd) + +REPO_DIR=${SCRIPT_DIR}/simpleRepo + +if [ ${#} -eq 1 ]; then + REPO_DIR=${1} +elif [ ${#} -gt 1 ]; then + exit +fi + +declaim "Creating empty repository: ${REPO_DIR}" +rm -rf ${REPO_DIR} +mkdir -vp ${REPO_DIR} +cd ${REPO_DIR} + +declaim "Initialising it as a git repository" +git init . + +git config --local user.name "Gaius Julius Caesar" +git config --local user.email "gjcaesar@pontifexmaximus.rm" + +declaim "Creating a text file" +cat < information.md + +# Test file + +This is a file for demonstration purposes + +EOF + +declaim "Adding and commiting that text file. The first commit" +git add information.md +git commit -m "commit1" + +declaim "Updating the text file" +echo "This is a second line of information." >> information.md +echo >> information.md + +declaim "Adding and commiting that text file. The second commit" +git add information.md +git commit -m "commit2" + +declaim "Updating the text file for the second time" +echo "This is a third line of information." >> information.md +echo >> information.md + +declaim "Adding and commiting that text file. The third commit" +git add information.md +git commit -m "commit3" + +declaim "Creating and checking out the Rel1 branch" +git checkout -b Rel1 + +declaim "Updating the text file on the Rel1 branch" +cat <> information.md + +# Rel1 information + +This is more information added as part of Rel1 + +EOF + +declaim "Adding and commiting that text file. The fourth commit" +git add information.md +git commit -m "commit4" + +declaim "Updating the text file on the Rel1 branch again" +mv -v information.md{,.hold} +cat information.md.hold | sed 's/of Rel1$/of Rel1./' > information.md +rm information.md.hold + +declaim "Adding and commiting that text file. The fifth commit" +git add information.md +git commit -m "commit5" + +declaim "Creating and checking out the Rel2 branch" +git checkout master +git checkout -b Rel2 + +declaim "Updating the text file on the Rel2 branch" +mv information.md{,.hold} +cat < information.md + +# Rel2 information + +This is more information added as part of Rel2 + +EOF +cat information.md.hold >> information.md +rm information.md.hold + +declaim "Adding and commiting that text file. The sixth commit" +git add information.md +git commit -m "commit6" + +declaim "Updating the text file on the Rel2 branch again" +mv information.md{,.hold} +cat information.md.hold | sed 's/of Rel2$/of Rel2./' > information.md +rm information.md.hold + +declaim "Adding and commiting that text file. The seventh commit" +git add information.md +git commit -m "commit7" + +declaim "Checking out master" +git checkout master + +git log --oneline --graph --decorate --all