diff --git a/content/tutorials/git_rewrite_history/.gitignore b/content/tutorials/git_rewrite_history/.gitignore new file mode 100644 index 000000000..c64a71a52 --- /dev/null +++ b/content/tutorials/git_rewrite_history/.gitignore @@ -0,0 +1,2 @@ +/.quarto/ +output diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/_extension.yml b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/_extension.yml new file mode 100644 index 000000000..52a98aa15 --- /dev/null +++ b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/_extension.yml @@ -0,0 +1,62 @@ +title: Reveal.js quarto extension with corporate identity of the Flemish government +author: Thierry Onkelinx +version: 0.0.1 +contributes: + knitr: + opts_chunk: + echo: false + message: false + warning: false + fig-height: 5.7 + fig-width: 12 + formats: + revealjs: + theme: [default, slides.scss] + css: entity.css + transition: convex + width: 1244 + height: 700 + navigation-mode: vertical + controls-layout: bottom-right + controls-tutorial: true + slide-number: c/t + show-slide-number: all + slide-level: 2 + email-obfuscation: javascript + embed-resources: true + chalkboard: false + preview-links: true + output-file: index.html + df-print: kable + progress: true + csl: research-institute-for-nature-and-forest.csl + template: partials/template.html + template-partials: + - partials/title-slide.html + format-resources: + - research-institute-for-nature-and-forest.csl + - css/entity.css + - fonts/FlandersArtSans-Bold.ttf + - fonts/FlandersArtSans-Light.ttf + - fonts/FlandersArtSans-Medium.ttf + - fonts/FlandersArtSans-Regular.ttf + - fonts/Inconsolata-Bold.ttf + - fonts/Inconsolata-Light.ttf + - fonts/Inconsolata-Medium.ttf + - fonts/Inconsolata-Regular.ttf + - img/flanders-en-intermediate.png + - img/flanders-en-slide.png + - img/flanders-en-title.png + - img/flanders-nl-intermediate.jpg + - img/flanders-nl-slide.jpg + - img/flanders-nl-transparent.png + - img/flanders-nl-title.png + - img/inbo-en-black.jpg + - img/inbo-en-title.png + - img/inbo-en-white.png + - img/inbo-nl-black.png + - img/inbo-nl-title.png + - img/inbo-nl-white.png + filters: + - filters/translations.lua + - filters/url.lua diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/css/entity.css b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/css/entity.css new file mode 100644 index 000000000..913c5ec77 --- /dev/null +++ b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/css/entity.css @@ -0,0 +1,107 @@ +.trapezium { + background: var(--flandersqmd-level1-trapezium); +} + +.reveal h1, .reveal h1 code { + color: var(--flandersqmd-level1-colour); +} + +.reveal h2, .reveal h2 code { + color: var(--flandersqmd-level2-colour); +} + +.reveal .title, .reveal .title code { + color: var(--flandersqmd-title-colour); +} + +.sidebar { + background-color: var(--flandersqmd-sidebar-bg); +} + +.sidebar-tussen { + background-color: var(--flandersqmd-level1-bg); +} + +.sidebar-url { + color: var(--flandersqmd-sidebar-colour); +} + +.sidebar-url-tussen { + color: var(--flandersqmd-sidebar-tussen-colour); +} + +.title-entity { + color: var(--flandersqmd-title-border); +} + +caption { + color: var(--flandersqmd-level2-colour); +} + +figcaption { + color: var(--flandersqmd-level2-colour); +} + +.reveal .slide aside, .reveal .slide div.aside { + color: var(--flandersqmd-footnote); +} + +.panel-tabset [role=tablist] { + border-bottom-color: var(--flandersqmd-border); +} + +.panel-tabset [role=tab] { + border-top-color: var(--flandersqmd-border); + border-left-color: var(--flandersqmd-border); + border-right-color: var(--flandersqmd-border); +} + +.panel-tabset [role=tab][aria-selected=true] { + border-top-color: var(--flandersqmd-border); + border-left-color: var(--flandersqmd-border); + border-right-color: var(--flandersqmd-border); +} + +.reveal div.callout.callout-note { + border-left-color: var(--flandersqmd-callout-note-border); +} + +.reveal div.callout.callout-note.callout-style-default .callout-title{ + background-color: var(--flandersqmd-callout-note-bg); +} + +.reveal div.callout.callout-tip { + border-left-color: var(--flandersqmd-callout-tip-border); +} + +.reveal div.callout.callout-tip.callout-style-default .callout-title{ + background-color: var(--flandersqmd-callout-tip-bg); +} + +.reveal div.callout.callout-caution { + border-left-color: var(--flandersqmd-callout-caution-border); +} + +.reveal div.callout.callout-caution.callout-style-default .callout-title{ + background-color: var(--flandersqmd-callout-caution-bg); +} + +.reveal div.callout.callout-warning { + border-left-color: var(--flandersqmd-callout-warning-border); +} + +.reveal div.callout.callout-note.warning-style-default .callout-title{ + background-color: var(--flandersqmd-callout-warning-bg); +} + +.reveal div.callout.callout-important { + border-left-color: var(--flandersqmd-callout-important-border); +} + +.reveal div.callout.callout-important.callout-style-default .callout-title{ + background-color: var(--flandersqmd-callout-important-bg); +} + +.photographer { + color: var(--flandersqmd-title-colour); +} diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/filters/translations.lua b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/filters/translations.lua new file mode 100644 index 000000000..0fbc02d75 --- /dev/null +++ b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/filters/translations.lua @@ -0,0 +1,225 @@ +function is_empty(s) + return s == nil or s == '' +end + +function entity_en(entity, level) + local result + if (entity == "INBO") then + result = { + url = "https://www.vlaanderen.be/inbo/en", + entity_name = "Research Institute for Nature and Forest (INBO)", + } + if is_empty(level) or tonumber(pandoc.utils.stringify(level)) < 2 then + result.entity_title_logo = "inbo-en-black.jpg" + else + result.entity_title_logo = "inbo-en-white.png" + end + else + result = { + url = "invalid `flandersqmd.entity`" + } + end + result.flanders_title_logo = "flanders-en-title.png" + result.flanders_alt = "Flanders, state of the art" + result.title_logo_style = "max-width: 205px;" + return result +end + +function entity_nl(entity, level) + local result + if (entity == "INBO") then + result = { + url = "https://www.vlaanderen.be/inbo", + entity_name = "Instituut voor Natuur- en Bosonderzoek (INBO)", + flanders_alt = "Vlaanderen is wetenschap" + } + if is_empty(level) or tonumber(pandoc.utils.stringify(level)) < 2 then + result.flanders_title_logo = "flanders-nl-intermediate.jpg" + result.entity_title_logo = "inbo-nl-black.png" + result.title_logo_style = "max-width: 245px;" + else + result.flanders_title_logo = "flanders-nl-transparent.png" + result.entity_title_logo = "inbo-nl-white.png" + result.title_logo_style = "max-width: 250px;" + end + else + result = { + url = "invalid `flandersqmd.entity`" + } + end + return result +end + +function translation(lang, entity, level) + if (lang == "nl-BE") then + result = entity_nl(entity, level) + else + result = entity_en(entity, level) + end + return result +end + +function display_person (person, i) + res = "" + if is_empty(person.name) then + res = '

!!! flandersqmd.authors element ' .. i .. ' has no name element!!!

' + return res + end + if is_empty(person.name.given) then + res = '

!!! flandersqmd.authors element ' .. i .. ' has no given element under name!!!

' + return res + end + if is_empty(person.name.family) then + res = '

!!! flandersqmd.authors element ' .. i .. ' has no given element under name!!!

' + return res + end + if is_empty(person.email) then + res = pandoc.utils.stringify(person.name.given) .. ' ' .. pandoc.utils.stringify(person.name.family) + else + res = res .. '' .. pandoc.utils.stringify(person.name.given) .. ' ' .. pandoc.utils.stringify(person.name.family) .. '' + end + if (is_empty(person.orcid)) then + return res + end + res = res .. ' ' + return res +end + +function title_author(author) + if is_empty(author) then + return '!!! Missing flandersqmd.author !!!' + end + z ='' + for i, person in pairs(author) do + z = z .. display_person(person, i) .. ' ' + end + return pandoc.RawInline('html', z) +end + +function levelcss (entity) + local css + css = ':root {\n' + css = css .. ' --flanders-white: #FFFFFF;\n' + css = css .. ' --inbo-darkblue: #282A72;\n' + css = css .. ' --inbo-darkblue-40: #282A7266;\n' + css = css .. ' --inbo-darkgreen: #006635;\n' + css = css .. ' --inbo-darkgreen-40: #00663566;\n' + css = css .. ' --inbo-orange: #EF972C;\n' + css = css .. ' --inbo-orange-40: #EF972C66;\n' + css = css .. ' --inbo-yellow: #FFCD34;\n' + css = css .. ' --inbo-yellow-40: #FFCD3466;\n' + css = css .. ' --inbo-red: #BE3254;\n' + css = css .. ' --inbo-red-40: #BE325466;\n' + if (entity == "inbo") then + css = css .. ' --inbo-black: #000000;\n' + css = css .. ' --inbo-gray: #8E9DA7;\n' + css = css .. ' --inbo-fushia: #C04384;\n' + css = css .. ' --inbo-blue: #356196;\n' + css = css .. ' --inbo-lightblue: #BDDDD7;\n' + + css = css .. ' --flandersqmd-border: var(--inbo-fushia);\n' + css = css .. ' --flandersqmd-callout-note-border: var(--inbo-darkblue);\n' + css = css .. ' --flandersqmd-callout-note-bg: var(--inbo-darkblue-40);\n' + css = css .. ' --flandersqmd-callout-tip-border: var(--inbo-darkgreen);\n' + css = css .. ' --flandersqmd-callout-tip-bg: var(--inbo-darkgreen-40);\n' + css = css .. ' --flandersqmd-callout-caution-border: var(--inbo-orange);\n' + css = css .. ' --flandersqmd-callout-caution-bg: var(--inbo-orange-40);\n' + css = css .. ' --flandersqmd-callout-warning-border: var(--inbo-yellow);\n' + css = css .. ' --flandersqmd-callout-warning-bg: var(--inbo-yellow-40);\n' + css = css .. ' --flandersqmd-callout-important-border: var(--inbo-red);\n' + css = css .. ' --flandersqmd-callout-important-bg: var(--inbo-red-40);\n' + css = css .. ' --flandersqmd-footnote: var(--inbo-gray);\n' + css = css .. ' --flandersqmd-level1-colour: var(--flanders-white);\n' + css = css .. ' --flandersqmd-level1-trapezium: var(--inbo-fushia);\n' + css = css .. ' --flandersqmd-level2-colour: var(--inbo-fushia);\n' + css = css .. ' --flandersqmd-link-colour: var(--inbo-blue);\n' + css = css .. ' --flandersqmd-sidebar-bg: var(--inbo-fushia);\n' + css = css .. ' --flandersqmd-sidebar-colour: var(--flanders-white);\n' + css = css .. ' --flandersqmd-sidebar-tussen-colour: var(--inbo-fushia);\n' + css = css .. ' --quarto-hl-fu-color: var(--inbo-black);\n' + css = css .. ' --r-link-color: var(--inbo-blue);\n' + css = css .. ' --r-link-color-hover: var(----inbo-lightblue);\n' + css = css .. ' --r-main-color: var(--inbo-black);\n' + else + css = css .. ' --flanders-canary-yellow: #FFED00;\n' + css = css .. ' --flanders-dark-yellow: #F0D70F;\n' + css = css .. ' --flanders-black: #3C3D3C;\n' + css = css .. ' --flanders-gray: #D5D5D5;\n' + css = css .. ' --flanders-dark-blue: #215E9E;\n' + css = css .. ' --flanders-light-blue: #32B2E9;\n' + + css = css .. ' --flandersqmd-border: var(--flanders-dark-yellow);\n' + css = css .. ' --flandersqmd-footnote: var(--flanders-gray);\n' + css = css .. ' --flandersqmd-level1-trapezium: var(--flanders-canary-yellow);\n' + css = css .. ' --flandersqmd-level1-colour: var(--flanders-black);\n' + css = css .. ' --flandersqmd-level2-colour: var(--flanders-dark-yellow);\n' + css = css .. ' --flandersqmd-link-colour: var(--flanders-dark-blue);\n' + css = css .. ' --flandersqmd-sidebar-bg: var(--flanders-canary-yellow);\n' + css = css .. ' --flandersqmd-sidebar-colour: var(--flanders-black);\n' + css = css .. ' --flandersqmd-sidebar-tussen-colour: var(--flanders-black);\n' + css = css .. ' --quarto-hl-fu-color: var(--flanders-black);\n' + css = css .. ' --r-link-color: var(--flanders-dark-blue);\n' + css = css .. ' --r-link-color-hover: var(--flanders-dark-blue);\n' + css = css .. ' --r-main-color: var(--flanders-black);\n' + end + css = css .. ' --flandersqmd-callout-note-border: var(--inbo-darkblue);\n' + css = css .. ' --flandersqmd-callout-note-bg: var(--inbo-darkblue-40);\n' + css = css .. ' --flandersqmd-callout-tip-border: var(--inbo-darkgreen);\n' + css = css .. ' --flandersqmd-callout-tip-bg: var(--inbo-darkgreen-40);\n' + css = css .. ' --flandersqmd-callout-caution-border: var(--inbo-orange);\n' + css = css .. ' --flandersqmd-callout-caution-bg: var(--inbo-orange-40);\n' + css = css .. ' --flandersqmd-callout-warning-border: var(--inbo-yellow);\n' + css = css .. ' --flandersqmd-callout-warning-bg: var(--inbo-yellow-40);\n' + css = css .. ' --flandersqmd-callout-important-border: var(--inbo-red);\n' + css = css .. ' --flandersqmd-callout-important-bg: var(--inbo-red-40);\n' + css = css .. ' --flandersqmd-title-colour: var(--flanders-white);\n' + css = css .. ' --flandersqmd-title-border: var(--flanders-white);\n' + css = css .. ' --flandersqmd-level1-bg: var(--flanders-white);\n' + css = css .. ' --r-main-font: flanders_art_sanslight, Calibri, Source Sans Pro, Helvetica, sans-serif;\n' + css = css .. ' --r-heading-font-weight: 400;\n' + css = css .. '}\n' + return css +end + +return { + { + Meta = function(meta) + if is_empty(meta.flandersqmd) then + meta.title = "No `flandersqmd` entry found in yaml" + meta.entitycolours = 'flanders' + meta.translation = translation( + pandoc.utils.stringify(meta.lang), "INBO" + ) + else + if is_empty(meta.flandersqmd.entity) then + meta.translation = translation( + pandoc.utils.stringify(meta.lang), "INBO", meta.flandersqmd.level + ) + else + meta.translation = translation( + pandoc.utils.stringify(meta.lang), + pandoc.utils.stringify(meta.flandersqmd.entity), + meta.flandersqmd.level + ) + end + if is_empty(meta.flandersqmd.title) then + meta.title = "missing `flandersqmd:title`" + else + meta.title = pandoc.utils.stringify(meta.flandersqmd.title) + end + if is_empty(meta.flandersqmd.level) or tonumber(pandoc.utils.stringify(meta.flandersqmd.level)) < 2 then + meta.entitycolours = 'flanders' + else + if is_empty(meta.flandersqmd.entity) then + meta.entitycolours = 'inbo' + else + meta.entitycolours = pandoc.text.lower(pandoc.utils.stringify(meta.flandersqmd.entity)) + end + end + meta.title_author = title_author(meta.flandersqmd.author) + end + meta.entitycss = levelcss(meta.entitycolours) + return meta + end, + } +} diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/filters/url.lua b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/filters/url.lua new file mode 100644 index 000000000..eb30855d2 --- /dev/null +++ b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/filters/url.lua @@ -0,0 +1,62 @@ +this_url = nil +this_lang = nil +entitycolours = nil + +function is_empty(s) + return s == nil or s == '' +end + +function Meta(meta) + this_url = pandoc.utils.stringify(meta.translation.url) + this_lang = pandoc.utils.stringify(meta.lang) + entitycolours = meta.entitycolours +end + +function Header(elem) + if not is_empty(this_lang) and elem.level == 1 and this_url then + local url_div = pandoc.Div({pandoc.Para({pandoc.Str(this_url)})}, pandoc.Attr("", {"sidebar-url-tussen"})) + ent_logo = pandoc.Div("", { class = "entity-tussen" }) + if (this_lang == "nl-BE") then + if (entitycolours == "inbo") then + vl_logo = pandoc.Image("Vlaanderen is wetenschap", "flanders-nl-transparent.png") + ent_logo = pandoc.Image("Instituut voor Natuur- en Bosonderzoek", "inbo-nl-white.png") + ent_logo.attr = {class = "entity-tussen"} + else + vl_logo = pandoc.Image("Vlaanderen, verbeelding werkt", "flanders-nl-intermediate.jpg") + end + vl_logo.attr = {class = "vl-tussen"} + else + if (entitycolours == "inbo") then + ent_logo = pandoc.Image("Instituut voor Natuur- en Bosonderzoek", "inbo-en-white.png") + ent_logo.attr = {class = "entity-tussen-vert"} + end + vl_logo = pandoc.Image("Flanders, state of the art", "flanders-en-intermediate.png") + vl_logo.attr = {class = "vl-tussen-vert"} + end + return { + elem, pandoc.Div("", { class = "trapezium" }), + pandoc.Div("", { class = "sidebar-tussen" }), vl_logo, ent_logo, url_div + } + elseif not is_empty(this_lang) and elem.level == 2 then + if (this_lang == "nl-BE") then + if (entitycolours == "inbo") then + vl_logo = pandoc.Image("Vlaanderen is wetenschap", "flanders-nl-title.png") + else + vl_logo = pandoc.Image("Vlaanderen is wetenschap", "flanders-nl-slide.jpg") + end + else + vl_logo = pandoc.Image("Vlaanderen is wetenschap", "flanders-en-slide.png") + end + vl_logo.attr = {class = "vl-slide"} + return {elem, vl_logo} + end + return elem +end + +function Pandoc(doc) + Meta(doc.meta) + doc.blocks = pandoc.walk_block(pandoc.Div(doc.blocks), { + Header = Header + }).content + return doc +end diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Bold.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Bold.ttf new file mode 100644 index 000000000..ade426637 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Bold.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Light.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Light.ttf new file mode 100644 index 000000000..577a2a07a Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Light.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Medium.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Medium.ttf new file mode 100644 index 000000000..1deb44983 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Medium.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Regular.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Regular.ttf new file mode 100644 index 000000000..a7b8d23b3 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/FlandersArtSans-Regular.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Bold.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Bold.ttf new file mode 100644 index 000000000..9f9272588 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Bold.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Light.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Light.ttf new file mode 100644 index 000000000..2ce184299 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Light.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Medium.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Medium.ttf new file mode 100644 index 000000000..364328355 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Medium.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Regular.ttf b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Regular.ttf new file mode 100644 index 000000000..457d262cf Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/fonts/Inconsolata-Regular.ttf differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-intermediate.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-intermediate.png new file mode 100644 index 000000000..5ff476ae4 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-intermediate.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-slide.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-slide.png new file mode 100644 index 000000000..8a15aa752 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-slide.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-title.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-title.png new file mode 100644 index 000000000..6e567f250 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-en-title.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-intermediate.jpg b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-intermediate.jpg new file mode 100644 index 000000000..55f6c3dd7 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-intermediate.jpg differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-slide.jpg b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-slide.jpg new file mode 100644 index 000000000..61a47d52d Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-slide.jpg differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-title.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-title.png new file mode 100755 index 000000000..66cd77495 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-title.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-transparent.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-transparent.png new file mode 100755 index 000000000..fb9cfaabe Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/flanders-nl-transparent.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-black.jpg b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-black.jpg new file mode 100644 index 000000000..55cca1103 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-black.jpg differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-title.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-title.png new file mode 100644 index 000000000..c437ebaca Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-title.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-white.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-white.png new file mode 100644 index 000000000..dff148d79 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-en-white.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-black.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-black.png new file mode 100644 index 000000000..f7b010d14 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-black.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-title.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-title.png new file mode 100755 index 000000000..d9de57120 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-title.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-white.png b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-white.png new file mode 100755 index 000000000..cb0b0ce35 Binary files /dev/null and b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/img/inbo-nl-white.png differ diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/research-institute-for-nature-and-forest.csl b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/research-institute-for-nature-and-forest.csl new file mode 100644 index 000000000..bad203bb5 --- /dev/null +++ b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/research-institute-for-nature-and-forest.csl @@ -0,0 +1,298 @@ + + diff --git a/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/slides.scss b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/slides.scss new file mode 100644 index 000000000..9699789f2 --- /dev/null +++ b/content/tutorials/git_rewrite_history/_extensions/inbo/flandersqmd/slides.scss @@ -0,0 +1,271 @@ +/*-- scss:defaults --*/ + +// Fonts + +$font-family-sans-serif: flanders_art_sans, Calibri, Source Sans Pro, Helvetica, sans-serif; +$font-family-monospace: inconsolata, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; + +@font-face { + font-family: flanders_art_sanslight; + src: url("../../../../../FlandersArtSans-Light.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: flanders_art_sansmedium; + src: url("../../../../../FlandersArtSans-Medium.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: flanders_art_sansregular; + src: url("../../../../../FlandersArtSans-Regular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: flanders_art_sansbold; + src: url("../../../../../FlandersArtSans-Bold.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: flanders_art_sans; + src: url("../../../../../FlandersArtSans-Light.ttf") format("truetype"); + font-weight: 300; + font-style: normal; +} +@font-face { + font-family: flanders_art_sans; + src: url("../../../../../FlandersArtSans-Medium.ttf") format("truetype"); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: flanders_art_sans; + src: url("../../../../../FlandersArtSans-Regular.ttf") format("truetype"); + font-weight: 500; + font-style: normal; +} +@font-face { + font-family: flanders_art_sans; + src: url("../../../../../FlandersArtSans-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: inconsolata; + src: url("../../../../../Inconsolata-Light.ttf") format("truetype"); + font-weight: 300; + font-style: normal; +} +@font-face { + font-family: inconsolata; + src: url("../../../../../Inconsolata-Medium.ttf") format("truetype"); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: inconsolata; + src: url("../../../../../Inconsolata-Regular.ttf") format("truetype"); + font-weight: 500; + font-style: normal; +} +@font-face { + font-family: inconsolata; + src: url("../../../../../Inconsolata-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; +} + +/*-- scss:rules --*/ + +.reveal h1 { + margin: 30% 10% 0% 10%; +} + +.subtitle { + font-size: 1.5em; + font-weight: bold; +} + +.date { + font-size: 1.5em; +} + +.reveal h1.title { + margin: 0% 0% 0% 0%; + font-size: 2em; +} + +#title-slide { + text-align: left; +} + +.reveal[data-navigation-mode="linear"] .title-slide h1 { + font-size: 2em; +} + +.title-logo { + position: fixed; + right: 0; + top: -120px; + height: 110px; + border: 0px; + padding: 0px; + margin: 0px; + text-align: center; + line-height: 1; +} + +.title-logo-img { + text-align: center; + margin: 2px !important; + max-width: 100% !important; +} + +.vl-tussen { + position: absolute; + left: 15px; + top: 5px; + width: 200px; +} + +.vl-tussen-vert { + position: absolute; + left: 15px; + top: 5px; + height: 200px; +} + +.entity-tussen { + position: absolute; + left: 15px; + top: 100px; + width: 200px; +} + +.entity-tussen-vert { + position: absolute; + left: 15px; + top: 210px; + width: 200px; +} + +.vl-slide { + position: absolute; + left: 0%; + bottom: -5%; + width: 200px; + z-index: -1; +} + +.coop-slide { + position: absolute; + right: 0%; + bottom: -5%; + width: 200px; + z-index: -1; +} + +.photographer { + font-size: 0.5em; + position: fixed; + bottom: 0px; + right: 0px; +} + +.sidebar { + position: fixed; + left: -70px; + bottom: -40px; + width: 50px; + height: 800px; +} + +.sidebar-tussen { + position: fixed; + left: -71px; + bottom: -40px; + width: 53px; + height: 800px; +} + +.sidebar-url { + font-size: 0.5em; + position: fixed; + writing-mode: vertical-rl; + transform: rotate(180deg); + display: inline-block; + left: -55px; + bottom: 0px; + width: 30px; + height: 700px; +} + +.sidebar-url-tussen { + font-size: 0.5em; + position: fixed; + writing-mode: vertical-rl; + transform: rotate(180deg); + display: inline-block; + left: -55px; + bottom: 0px; + width: 30px; + height: 700px; +} + +.fontsize-0-5 { + font-size: 0.5em; +} + +.fontsize-0-6 { + font-size: 0.6em; +} + +.fontsize-0-7 { + font-size: 0.7em; +} + +.fontsize-0-8 { + font-size: 0.8em; +} + +.fontsize-0-9 { + font-size: 0.9em; +} + +.trapezium { + z-index: -100; + position: absolute; + left: 0%; + top: 0%; + clip-path: polygon(0% 0%, 80% 0%, 100% 100%, 0% 100%); + width: 100%; + height: 700px; +} + +caption { + text-align: center; +} + +figcaption { + text-align: center; +} + +.dataTables_wrapper .dataTables_paginate { + font-size: 35%; +} + +.reveal .slide aside, .reveal .slide div.aside { + bottom: 50px; +} + +.reveal pre { + font-size: inherit; +} + +.reveal code { + font-size: inherit; +} diff --git a/content/tutorials/git_rewrite_history/_quarto.yml b/content/tutorials/git_rewrite_history/_quarto.yml new file mode 100644 index 000000000..a020f833d --- /dev/null +++ b/content/tutorials/git_rewrite_history/_quarto.yml @@ -0,0 +1,28 @@ +project: + type: default + preview: + port: 4201 + browser: true + render: + - presentation.qmd + output-dir: output + post-render: post_render.R + +lang: en-GB + +format: flandersqmd-revealjs + +flandersqmd: + entity: INBO + level: 2 + title: Rewriting git history + author: + - name: + given: Thierry + family: Onkelinx + email: thierry.onkelinx@inbo.be + orcid: 0000-0001-8804-4216 + affiliation: + - Research Institute for Nature and Forest (INBO) + date: '2026-03-05' + cover: pexels-erfin-ekarana-494408160-28216541.jpg diff --git a/content/tutorials/git_rewrite_history/index.md b/content/tutorials/git_rewrite_history/index.md new file mode 100644 index 000000000..704230503 --- /dev/null +++ b/content/tutorials/git_rewrite_history/index.md @@ -0,0 +1,17 @@ +--- +title: "Rewriting git history" +description: "A presentation on rewriting git history" +authors: [thierryo] +date: 2026-03-05 +categories: ["version control"] +tags: ["version control", "git", "github"] +output: + md_document: + preserve_yaml: true + variant: gfm+footnotes +--- + +This [presentation](presentation.html) gives some basic instructions on rewriting git history. +Use the `F11` function key to display the presentation full screen. +Use the spacebar and arrow keys to navigate in the presentation. +Use the `F5` function key to refresh the page when the labels in the graphics are missing or misplaced. \ No newline at end of file diff --git a/content/tutorials/git_rewrite_history/pexels-erfin-ekarana-494408160-28216541.jpg b/content/tutorials/git_rewrite_history/pexels-erfin-ekarana-494408160-28216541.jpg new file mode 100644 index 000000000..4348fb517 Binary files /dev/null and b/content/tutorials/git_rewrite_history/pexels-erfin-ekarana-494408160-28216541.jpg differ diff --git a/content/tutorials/git_rewrite_history/post_render.R b/content/tutorials/git_rewrite_history/post_render.R new file mode 100644 index 000000000..00a001e65 --- /dev/null +++ b/content/tutorials/git_rewrite_history/post_render.R @@ -0,0 +1,16 @@ +library(yaml) +list.files( + "_extensions", + pattern = "_extension.yml", + full.names = TRUE, + recursive = TRUE +) |> + grepv(pattern = "flandersqmd") |> + read_yaml() -> resources +resources$contributes$format$revealjs[["format-resources"]] |> + basename() |> + file.remove() -> hide +file.copy("output/index.html", "presentation.html", overwrite = TRUE) -> hide +list.files("output", recursive = TRUE, full.names = TRUE) |> + file.remove() -> hide +rm(hide) \ No newline at end of file diff --git a/content/tutorials/git_rewrite_history/presentation.html b/content/tutorials/git_rewrite_history/presentation.html new file mode 100644 index 000000000..3cd78491f --- /dev/null +++ b/content/tutorials/git_rewrite_history/presentation.html @@ -0,0 +1,4792 @@ + + + + + + + + + + + + presentation + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+

Refresher on git basics

+
+ +
+ +Flanders, state of the art +Instituut voor Natuur- en Bosonderzoek + +
+
+

The commit

+Vlaanderen is wetenschap +
+
+
+
+ +
+

content

+
+
+
    +
  • which files to change
  • +
  • how to change the files
  • +
  • when (timestamp)
  • +
  • by whom (author)
  • +
  • description (message)
  • +
  • previous commit
  • +
+
+
+
+
+
+
+
+ +
+

commit hash

+
+
+
    +
  • sha1 digest of content
  • +
  • references the commit
  • +
+
+
+
+
+
+

Commands

+Vlaanderen is wetenschap +

git add README.md

+
    +
  • select README.md to be added to the next commit
  • +
+

git commit -m "initial commit"

+
    +
  • create a commit with message “initial commit”
  • +
+
+
+

Git history

+Vlaanderen is wetenschap +
+
+
+

+
+ + +G + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +HEAD + +HEAD + + + +HEAD->m3 + + + + +
+

+
+
+
+
+
+

Going back in time

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +HEAD + +HEAD + + + +HEAD->m3 + + + + +
+

+
+
+
+
+
    +
  • git checkout m2
  • +
  • changes the files under version control in your working directory
  • +
  • detached HEAD state
  • +
+
+
+
+

Creating a new branch

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +HEAD + +HEAD + + + +HEAD->m2 + + + + +my_feature + +my_feature + + + +my_feature->m2 + + + + +
+

+
+
+
+
+
    +
  • git branch my_feature +
      +
    • always at the current checkout position
    • +
  • +
  • git checkout my_feature +
      +
    • switch to the new branch
    • +
  • +
+
+
+
+

Committing to current branch

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f1 + +f1 + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->f1 + + + + +
+

+
+
+
+
+
    +
  • git add
  • +
  • git commit
  • +
+
+
+
+

git push -u origin my_feature

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + +cluster_local + +local + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f1 + +f1 + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->f1 + + + + +origin_my_feature + +origin/my_feature + + + +origin_my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->f1 + + + + +
+

+
+
+
+
+
+
+
+

+
+ + +G + + +cluster_local + +origin + + + +m2 + +m2 + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f1 + +f1 + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->f1 + + + + +
+

+
+
+
+
+
+
+
+

Rewriting history locally

+
+ +
+ +Flanders, state of the art +Instituut voor Natuur- en Bosonderzoek + +
+
+

Assumptions

+Vlaanderen is wetenschap +
    +
  • you are the only person working on the commits
  • +
  • you haven’t pushed the involved commits
  • +
+
+
+

Problem in the most recent commit

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f3 + +f3 + + + +f2 + +f2 + + + +f3->f2 + + + + + +f1 + +f1 + + + +f2->f1 + + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->f3 + + + + +origin_my_feature + +origin/my_feature + + + +origin_my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->f3 + + + + +
+

+
+
+
+
+
    +
  • correct files
  • +
  • stage them with git add
  • +
  • git commit --amend +
      +
    • alters the last commit instead of creating a new commit
    • +
  • +
  • note that the commit hash will change
  • +
+
+
+
+

Resetting

+Vlaanderen is wetenschap +
    +
  • git reset +
      +
    • unstage all stages changes
    • +
    • doesn’t change files
    • +
  • +
  • git reset --hard +
      +
    • revert all changes to the status of the latest commit
    • +
  • +
  • git reset --hard HEAD~1 +
      +
    • remove the latest commit
    • +
    • revert all changes to the status of the current latest commit
    • +
  • +
+
+
+

Rebase

+Vlaanderen is wetenschap +
    +
  • add commits from one branch at the end of the another branch
  • +
+
    +
  1. go the branch to which you want to add commits +
      +
    • git checkout my_feature
    • +
  2. +
  3. rebase the branch you want to add +
      +
    • git rebase other_feature
    • +
  4. +
+
+
+

Git rebase visualised

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + +cluster + +before + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f3 + +f3 + + + +f2 + +f2 + + + +f3->f2 + + + + + +f1 + +f1 + + + +f2->f1 + + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->f3 + + + + +origin_my_feature + +origin/my_feature + + + +origin_my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->f3 + + + + +g0 + +g0 + + + +g0->f1 + + + + + +g1 + +g1 + + + +g1->g0 + + + + + +other_feature + +other_feature + + + +other_feature->g1 + + + + +
+

+
+
+
+
+
+
+
+

+
+ + +G + + +cluster + +after + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +g1b + +g1b + + + +g0b + +g0b + + + +g1b->g0b + + + + + +f3 + +f3 + + + +g0b->f3 + + + + + +f2 + +f2 + + + +f3->f2 + + + + + +f1 + +f1 + + + +f2->f1 + + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->g1b + + + + +origin_my_feature + +origin/my_feature + + + +origin_my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->g1b + + + + +
+

+
+
+
+
+
+
+

Cherry-pick

+Vlaanderen is wetenschap +
    +
  • add one or more individual commits from one branch at the end of the another branch
  • +
+
    +
  1. go the branch to which you want to add commits +
      +
    • git checkout my_feature
    • +
  2. +
  3. cherry-pick the commit you want to add +
      +
    • git cherry-pick g1
    • +
  4. +
+
+
+

Git cherry-pick visualised

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + +cluster + +before + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f3 + +f3 + + + +f2 + +f2 + + + +f3->f2 + + + + + +f1 + +f1 + + + +f2->f1 + + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->f3 + + + + +origin_my_feature + +origin/my_feature + + + +origin_my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->f3 + + + + +g0 + +g0 + + + +g0->f1 + + + + + +g1 + +g1 + + + +g1->g0 + + + + + +other_feature + +other_feature + + + +other_feature->g1 + + + + +
+

+
+
+
+
+
+
+
+

+
+ + +G + + +cluster + +after + + + +main + +main + + + +m3 + +m3 + + + +main->m3 + + + + +m2 + +m2 + + + +m3->m2 + + + + + +m1 + +m1 + + + +m2->m1 + + + + + +m0 + +m0 + + + +m1->m0 + + + + + +g1b + +g1b + + + +f3 + +f3 + + + +g1b->f3 + + + + + +f2 + +f2 + + + +f3->f2 + + + + + +f1 + +f1 + + + +f2->f1 + + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m2 + + + + + +my_feature + +my_feature + + + +my_feature->g1b + + + + +origin_my_feature + +origin/my_feature + + + +origin_my_feature->f1 + + + + +HEAD + +HEAD + + + +HEAD->g1b + + + + +g0 + +g0 + + + +g0->f1 + + + + + +g1 + +g1 + + + +g1->g0 + + + + + +other_feature + +other_feature + + + +other_feature->g1 + + + + +
+

+
+
+
+
+
+
+

Interactive rebase

+Vlaanderen is wetenschap +
    +
  • allows to change older commits
  • +
+
    +
  1. make sure you have checked out the correct branch +
      +
    • git checkout my_feature
    • +
  2. +
  3. define the range of commits you want to alter +
      +
    • git rebase -i f2 start at commit f2
    • +
    • git rebase -i HEAD~2 start 2 commits before HEAD
    • +
  4. +
+
+
+

Interactive rebase

+Vlaanderen is wetenschap +
    +
  1. indicate what you want to do with every commit +
      +
    • pick: use as is
    • +
    • edit: change the commit
    • +
    • drop: remove the commit
    • +
  2. +
+
+
+

Interactive rebase

+Vlaanderen is wetenschap +
    +
  1. rebase will automatically checkout the first edit commit +
      +
    • correct the files
    • +
    • git add changed files
    • +
    • git commit --amend to update commit
    • +
    • git rebase --continue to continue the process
    • +
  2. +
+

Use git rebase --abort to undo the changes while the rebase is in progress.

+
+
+
+

Rewriting history on a remote repository

+
+ +
+ +Flanders, state of the art +Instituut voor Natuur- en Bosonderzoek + +
+
+

Precautions

+Vlaanderen is wetenschap +
    +
  • warn all active users to stop pushing and pulling until you’re done
  • +
  • make sure no one has created a branch start from the range you want to alter +
      +
    • merge such branches before rewriting the history
    • +
  • +
  • do the work in a different git clone
  • +
  • create a new branch before altering a branch
  • +
+
+
+

Workflow

+Vlaanderen is wetenschap +
    +
  • apply the changes locally as described in the previous chapter
  • +
  • a simple git push will fail because of a diverging history
  • +
  • you must use git push --force or git push -f
  • +
  • be careful because you can’t undo that
  • +
+
+
+

Get updated branch in other clone

+Vlaanderen is wetenschap +
    +
  1. Checkout the local branch +
      +
    • git checkout <branch-name>
    • +
  2. +
  3. Get new branches from remote +
      +
    • git fetch origin
    • +
  4. +
  5. Reset to the new origin branch +
      +
    • git reset --hard origin/<branch-name>
    • +
  6. +
+
+
+

Recreate a release by remerging a branch

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m1 + +m1 + + + +main->m1 + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f1 + +f1 + + + +m1->f1 + + + + + +omain + +origin/main + + + +omain->m1 + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m0 + + + + + +HEAD + +HEAD + + + +HEAD->m1 + + + + +
+

+
+
+
+
+
    +
  1. Delete the release and the related tag on GitHub
  2. +
  3. git checkout main: go to the main branch
  4. +
  5. git pull: make sure you have the latest main
  6. +
+
+
+
+

Recreate a release by remerging a branch

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m1 + +m1 + + + +main->m1 + + + + +m0 + +m0 + + + +m1->m0 + + + + + +f1 + +f1 + + + +m1->f1 + + + + + +omain + +origin/main + + + +omain->m1 + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m0 + + + + + +feature + +feature + + + +feature->f1 + + + + +ofeature + +origin/feature + + + +ofeature->f1 + + + + +HEAD + +HEAD + + + +HEAD->f1 + + + + +
+

+
+
+
+
+
    +
  1. git checkout <commit-SHA>: go the latest commit of the feature branch
  2. +
  3. git branch <branch_name>: recreate the feature branch
  4. +
  5. git push -u origin <branch_name>: push the feature branch
  6. +
+
+
+
+

Recreate a release by remerging a branch

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m0 + +m0 + + + +main->m0 + + + + +omain + +origin/main + + + +omain->m0 + + + + +f1 + +f1 + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m0 + + + + + +feature + +feature + + + +feature->f1 + + + + +ofeature + +origin/feature + + + +ofeature->f1 + + + + +HEAD + +HEAD + + + +HEAD->m0 + + + + +
+

+
+
+
+
+
    +
  1. git checkout main: go back to the main branch
  2. +
  3. git reset --hard HEAD~1: remove the latest commit of the main branch
  4. +
  5. git push -f: force push the main branch
  6. +
+
+
+
+

Recreate a release by remerging a branch

+Vlaanderen is wetenschap +
+
+
+
+
+

+
+ + +G + + + +main + +main + + + +m0 + +m0 + + + +main->m0 + + + + +omain + +origin/main + + + +omain->m0 + + + + +f2 + +f2 + + + +f1 + +f1 + + + +f2->f1 + + + + + +f0 + +f0 + + + +f1->f0 + + + + + +f0->m0 + + + + + +feature + +feature + + + +feature->f2 + + + + +ofeature + +origin/feature + + + +ofeature->f2 + + + + +HEAD + +HEAD + + + +HEAD->f2 + + + + +
+

+
+
+
+
+
    +
  1. git checkout <feature_branch>: go back to the feature branch
  2. +
  3. alter the <feature_branch>
  4. +
  5. git push -f
  6. +
  7. create a new pull request
  8. +
  9. merge pull request
  10. +
+
+
+
+
+

Git recommendations

+
+ +
+ +Flanders, state of the art +Instituut voor Natuur- en Bosonderzoek + +
+
+

Keep your commits small

+Vlaanderen is wetenschap +
    +
  • easier to give a good description
  • +
  • easier to read history
  • +
  • easier to revert changes
  • +
  • easier to cherry-pick
  • +
+

You don’t have to commit all changes of a file in a single commit!

+
+
+

Agree on a workflow

+Vlaanderen is wetenschap +
    +
  • don’t work in the main branch
  • +
  • protect the main branch on GitHub
  • +
  • use pull request on GitHub to add feature branches to the main branch
  • +
  • only one person at a time should work in a branch
  • +
+
+
+

Use checklist

+Vlaanderen is wetenschap +
    +
  • add an improved .gitignore
  • +
  • adds a lot of automated checks
  • +
+
+
+

Saperlipopette

+Vlaanderen is wetenschap +

Saperlipopette creates Git exercises, that users solve using their local and usual tools.

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/tutorials/git_rewrite_history/presentation.qmd b/content/tutorials/git_rewrite_history/presentation.qmd new file mode 100644 index 000000000..20f05b131 --- /dev/null +++ b/content/tutorials/git_rewrite_history/presentation.qmd @@ -0,0 +1,653 @@ +# Refresher on git basics + +## The commit + +::: {.callout-note} +### content + +- which files to change +- how to change the files +- when (timestamp) +- by whom (author) +- description (message) +- previous commit +::: + +::: {.callout-tip} +### commit hash + +- sha1 digest of content +- references the commit +::: + +## Commands + +### `git add README.md` + +- select `README.md` to be added to the next commit + +### `git commit -m "initial commit"` + +- create a commit with message "initial commit" + +## Git history + +```{dot} +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m3 [dir = none, color="#019966"]; + m3 -> m2 -> m1 -> m0; + HEAD -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + m3 [color = "#C04384"] +} +``` + +## Going back in time + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m3 [dir = none, color="#019966"]; + m3 -> m2 -> m1 -> m0; + HEAD -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + m2 [color = "#C04384"] +} +``` + +::: + +::: {.column} + +- `git checkout m2` +- changes the files under version control in your working directory +- detached HEAD state + +::: + +:::: + +## Creating a new branch + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m3 [dir = none, color="#019966"]; + m3 -> m2 -> m1 -> m0; + HEAD -> m2 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> m2 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + m2 [color = "#C04384"] +} +``` + +::: + +::: {.column} + +- `git branch my_feature` + - always at the current checkout position +- `git checkout my_feature` + - switch to the new branch + +::: + +:::: + + +## Committing to current branch + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> f1 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] +} +``` + +::: + +::: {.column} + + +- `git add` +- `git commit` + +::: + +:::: + + +## `git push -u origin my_feature` + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + compound=true; + subgraph cluster_local { + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> f1 [dir = none, color="#019966"]; + origin_my_feature [shape = diamond, color="#019966", label = "origin/my_feature", style=filled, fillcolor = "#BDDDD7"]; + origin_my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> f1 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] + label = "local"; + } +} +``` + +::: + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + compound=true; + subgraph cluster_local { + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + m2 -> m1 -> m0; + f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> f1 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] + label = "origin"; + } +} +``` +::: + +:::: + +# Rewriting history locally + +## Assumptions + +- you are the only person working on the commits +- you haven't pushed the involved commits + +## Problem in the most recent commit + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + f3 -> f2 -> f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> f3 [dir = none, color="#019966"]; + origin_my_feature [shape = diamond, color="#019966", label = "origin/my_feature", style=filled, fillcolor = "#BDDDD7"]; + origin_my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> f3 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f2 [style = filled, fillcolor = "#BDDDD7"] + f3 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] +} +``` + +::: + +::: {.column} +- correct files +- stage them with `git add` +- `git commit --amend` + - alters the last commit instead of creating a new commit +- note that the commit hash will change +::: + +:::: + +## Resetting + +- `git reset` + - unstage all stages changes + - doesn't change files +- `git reset --hard` + - revert all changes to the status of the latest commit +- `git reset --hard HEAD~1` + - remove the latest commit + - revert all changes to the status of the current latest commit + +## Rebase + +- add commits from one branch at the end of the another branch + +1. go the branch to which you want to add commits + - `git checkout my_feature` +1. rebase the branch you want to add + - `git rebase other_feature` + +## Git rebase visualised + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + subgraph cluster { + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + f3 -> f2 -> f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> f3 [dir = none, color="#019966"]; + origin_my_feature [shape = diamond, color="#019966", label = "origin/my_feature", style=filled, fillcolor = "#BDDDD7"]; + origin_my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> f3 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f2 [style = filled, fillcolor = "#BDDDD7"] + f3 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] + g0 [style = filled, fillcolor = "#EF972C"] + g1 [style=filled, fillcolor = "#EF972C"] + g1 -> g0 -> f1 [color = "#EF972C"]; + other_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#EF972C"]; + other_feature -> g1 [dir = none, color="#019966"]; + label = "before" + } +} +``` + +::: + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + subgraph cluster { + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + g1b -> g0b -> f3 -> f2 -> f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> g1b [dir = none, color="#019966"]; + origin_my_feature [shape = diamond, color="#019966", label = "origin/my_feature", style=filled, fillcolor = "#BDDDD7"]; + origin_my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> g1b [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f2 [style = filled, fillcolor = "#BDDDD7"] + f3 [style=filled, fillcolor = "#BDDDD7"] + g0b [style = filled, fillcolor = "#EF972C"] + g1b [color = "#C04384", style=filled, fillcolor = "#EF972C"] + label = "after" + } +} +``` +::: + +:::: + +## Cherry-pick + +- add one or more individual commits from one branch at the end of the another branch + +1. go the branch to which you want to add commits + - `git checkout my_feature` +1. cherry-pick the commit you want to add + - `git cherry-pick g1` + +## Git cherry-pick visualised + +:::: {.columns} + +::: {.column} + +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + subgraph cluster { + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + f3 -> f2 -> f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> f3 [dir = none, color="#019966"]; + origin_my_feature [shape = diamond, color="#019966", label = "origin/my_feature", style=filled, fillcolor = "#BDDDD7"]; + origin_my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> f3 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f2 [style = filled, fillcolor = "#BDDDD7"] + f3 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] + g0 [style = filled, fillcolor = "#EF972C"] + g1 [style=filled, fillcolor = "#EF972C"] + g1 -> g0 -> f1 [color = "#EF972C"]; + other_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#EF972C"]; + other_feature -> g1 [dir = none, color="#019966"]; + label = "before" + } +} +``` + +::: + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + subgraph cluster { + main -> m3 [dir = none, color="#019966"]; + main [shape = diamond, color="#019966"]; + m3 -> m2 -> m1 -> m0; + g1b -> f3 -> f2 -> f1 -> f0 -> m2 [color = "#BDDDD7"]; + my_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#BDDDD7"]; + my_feature -> g1b [dir = none, color="#019966"]; + origin_my_feature [shape = diamond, color="#019966", label = "origin/my_feature", style=filled, fillcolor = "#BDDDD7"]; + origin_my_feature -> f1 [dir = none, color="#019966"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> g1b [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f2 [style = filled, fillcolor = "#BDDDD7"] + f3 [color = "#C04384", style=filled, fillcolor = "#BDDDD7"] + g0 [style = filled, fillcolor = "#EF972C"] + g1 [style=filled, fillcolor = "#EF972C"] + g1b [style=filled, fillcolor = "#EF972C"] + g1 -> g0 -> f1 [color = "#EF972C"]; + other_feature [shape = diamond, color="#019966", style=filled, fillcolor = "#EF972C"]; + other_feature -> g1 [dir = none, color="#019966"]; + label = "after" + } +} +``` +::: + +:::: + +## Interactive rebase + +- allows to change older commits + +1. make sure you have checked out the correct branch + - `git checkout my_feature` +1. define the range of commits you want to alter + - `git rebase -i f2` start at commit f2 + - `git rebase -i HEAD~2` start 2 commits before HEAD + +## Interactive rebase + +3. indicate what you want to do with every commit + - `pick`: use as is + - `edit`: change the commit + - `drop`: remove the commit + +## Interactive rebase + +4. rebase will automatically checkout the first `edit` commit + - correct the files + - `git add` changed files + - `git commit --amend` to update commit + - `git rebase --continue` to continue the process + +Use `git rebase --abort` to undo the changes while the rebase is in progress. + +# Rewriting history on a remote repository + +## Precautions + +- warn all active users to stop pushing and pulling until you're done +- make sure no one has created a branch start from the range you want to alter + - merge such branches before rewriting the history +- do the work in a different `git clone` +- create a new branch before altering a branch + +## Workflow + +- apply the changes locally as described in the previous chapter +- a simple `git push` will fail because of a diverging history +- you must use `git push --force` or `git push -f` +- be careful because you can't undo that + +## Get updated branch in other clone + +1. Checkout the local branch + - `git checkout ` +1. Get new branches from remote + - `git fetch origin` +1. Reset to the new origin branch + - `git reset --hard origin/` + +## Recreate a release by remerging a branch + +:::: {.columns} + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m1 [dir = none, color="#019966"]; + omain -> m1 [dir = none, color="#019966"]; + m1 -> m0; + f1 -> f0 -> m0 [color = "#BDDDD7"]; + m1 -> f1; + main [shape = diamond, color="#019966"]; + omain [shape = diamond, color="#019966", label = "origin/main"]; + HEAD [shape = diamond, color="#019966"]; + HEAD -> m1 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + m1 [color = "#C04384"] +} +``` +::: + +::: {.column} +1. Delete the release and the related tag on GitHub +1. `git checkout main`: go to the `main` branch +1. `git pull`: make sure you have the latest `main` +::: + +:::: + + +## Recreate a release by remerging a branch + +:::: {.columns} + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m1 [dir = none, color="#019966"]; + omain -> m1 [dir = none, color="#019966"]; + m1 -> m0; + f1 -> f0 -> m0 [color = "#BDDDD7"]; + m1 -> f1; + main [shape = diamond, color="#019966"]; + omain [shape = diamond, color="#019966", label = "origin/main"]; + feature [shape = diamond, color="#019966"]; + ofeature [shape = diamond, color="#019966", label = "origin/feature"]; + HEAD [shape = diamond, color="#019966"]; + feature -> f1 [dir = none, color="#019966"]; + ofeature -> f1 [dir = none, color="#019966"]; + HEAD -> f1 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f1 [color = "#C04384"] +} +``` +::: + +::: {.column} +4. `git checkout `: go the latest commit of the feature branch +1. `git branch `: recreate the feature branch +1. `git push -u origin `: push the feature branch +::: + +:::: + +## Recreate a release by remerging a branch + +:::: {.columns} + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m0 [dir = none, color="#019966"]; + omain -> m0 [dir = none, color="#019966"]; + m0; + f1 -> f0 -> m0 [color = "#BDDDD7"]; + main [shape = diamond, color="#019966"]; + omain [shape = diamond, color="#019966", label = "origin/main"]; + feature [shape = diamond, color="#019966"]; + ofeature [shape = diamond, color="#019966", label = "origin/feature"]; + HEAD [shape = diamond, color="#019966"]; + feature -> f1 [dir = none, color="#019966"]; + ofeature -> f1 [dir = none, color="#019966"]; + HEAD -> m0 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + m0 [color = "#C04384"] +} +``` +::: + +::: {.column} +7. `git checkout main`: go back to the main branch +1. `git reset --hard HEAD~1`: remove the latest commit of the main branch +1. `git push -f`: force push the main branch +::: + +:::: + +## Recreate a release by remerging a branch + +:::: {.columns} + +::: {.column} +```{dot} +//| fig-width: 6 +digraph G { + rankdir="TB"; + node [fontname="FlandersArtSans-Bold.ttf,sans-serif"] + main -> m0 [dir = none, color="#019966"]; + omain -> m0 [dir = none, color="#019966"]; + m0; + f2 -> f1 -> f0 -> m0 [color = "#BDDDD7"]; + main [shape = diamond, color="#019966"]; + omain [shape = diamond, color="#019966", label = "origin/main"]; + feature [shape = diamond, color="#019966"]; + ofeature [shape = diamond, color="#019966", label = "origin/feature"]; + HEAD [shape = diamond, color="#019966"]; + feature -> f2 [dir = none, color="#019966"]; + ofeature -> f2 [dir = none, color="#019966"]; + HEAD -> f2 [dir = none, color="#019966"]; + f0 [style = filled, fillcolor = "#BDDDD7"] + f1 [style = filled, fillcolor = "#BDDDD7"] + f2 [style = filled, fillcolor = "#BDDDD7"] + f2 [color = "#C04384"] +} +``` +::: + +::: {.column} +10. `git checkout `: go back to the feature branch +1. alter the `` +1. `git push -f` +1. create a new pull request +1. merge pull request +::: + +:::: + +# Git recommendations + +## Keep your commits small + +- easier to give a good description +- easier to read history +- easier to revert changes +- easier to cherry-pick + +You don't have to commit all changes of a file in a single commit! + +## Agree on a workflow + +- don't work in the `main` branch +- protect the `main` branch on GitHub +- use `pull request` on GitHub to add feature branches to the main branch +- only one person at a time should work in a branch + +## Use `checklist` + +- add an improved `.gitignore` +- adds a lot of automated checks + +## Saperlipopette + +[Saperlipopette](https://docs.ropensci.org/saperlipopette/articles/saperlipopette.html) creates Git exercises, that users solve using their local and usual tools.