git
und die darauf basierenden Hosting-Services Github und Gitlab sind Tools zur Versionskontrolle, die im Entwicklungskontext den De-Facto Industriestandard darstellen.
Der Grund für diesen Erfolg ist dabei die Baum-artige Struktur in der Änderungen am Code-Stamm getracked und nachvollzogen werden können.
Über verschiedene “branches” können außerdem Änderungen gebaut, erweitert und getestet werden, bevor sie in den zentralen Codestamm (bei Github der “main”-branch) “gemerged” werden.
Dabei ist es generell möglich, Änderungen in allen möglichen Dateiformaten zu tracken, so richtig sinnvoll sind Änderungen und Änderungsabschnitte aber vor allem in Klartextformaten ohne Serialisierung verständlich.
Textfiles müssen aber ja nicht notwendigerweise nur Code enthalten.
Mit der wachsenden Beliebtheit von Rmarkdown und neuerdings Quarto geht (zumindest in der R-Community) der Trend zum Verfassen von Texten in auf markdown basierenden Formaten, die mit Hilfe von Pandoc in andere Formate kompiliert werden können.
Da diese Formate in einfachen Textfiles abgespeichert werden, können so die Vorteile von git zum Tragen kommen.
Ein workflow zum gemeinsamen Erstellen von Texten wie er zum Beispiel beim Schreiben gemeinsamer Publikationen nötig ist, gestützt auf eins der populären markdown Formate und git, könnte eine echte Alternative zur Co-Autorenschaft in Word sein.
Dabei hat der vorgeschlagene Workflow die folgenden Vorteile:
- Quarto/Rmarkdown1 haben auch ohne Kombination mit git Vorteile beim Erstellen und Einbinden von Grafiken, Tabellen und statistischen Ergebnissen
- mit git kommt ein Versionsmanagement dazu, dass Änderungen verfolgbar und auch zurückziehbar macht, ohne dass die Festplatte voll von
manuskript_final_v1_v3.docx
etc. wird - die gesamte Änderungsgeschichte ließe sich publizieren, was aus Gesichtspunkten offener Wissenschaft attraktiv sein kann. Muss aber nicht.
- mit Github/Gitlab Issues kommt ein ganzer Stack an Projektmanagement-Tools dazu, der optional genutzt werden kann
- mit Github/Gitlab Action lassen sich Tests und Updates vor oder beim Commit automatisieren
- das Zusammenarbeiten über Betriebssystem-Grenzen hinweg ist problemlos. Kein Ärger mehr mit verschiedenen Office-Versionen oder Formatierungskonflikten zwischen MS Office und Open Scource Lösungen
Dabei sind die Nachteile relativ gering - Quarto ist sehr weit gekommen und unterstützt alle Standard-Anforderungen an akademische Arbeiten - Zitieren, Formatieren und das Nutzen von Latex-Templates ist kein Problem.
Dazu kommt dass zumindest bei der Nutzung von RStudio seit kurzem auch eine WYSIWYG-Lösung zur Texteditirung dazugekommen ist - die Bedienung des Visual Editors sollte Leuten, die an Word gewöhnt sind, keine so große Herausforderunge mehr bereiten wie das Schreiben in reinem markdown
.
Der einzige größere Nachteil ist, dass sich der Ablauf zum Kommentieren ändert - dazu kommen wir aber später.
Einrichtung
Unter Mac und Unix-Distros ist git vorinstalliert, unter Windows muss der Client noch installiert werden: Download git
Um Änderungen darzustellen gibt es zwar auch Funktionalität in RStudio, die github Desktop-GUI ist aber auch ganz schick: Download github Desktop
Rstudio als IDE bietet sich an, hier wird aber davon ausgegangen, dass die Installation bereits passiert ist.
Außerdem ist zum Einbinden von Zitationen in Quarto-Texten eine Zotero-Installation mit dem Better Bibtex Addon zu empfehlen.
Im visuellen Editor gibt es einen eigenständigen Zitationsmanger mit Zotero-Connection, im Source-Editor habe ich aber bessere Erfahrungen mit dem citr
-Paket gemacht, das es leider nicht mehr auf Cran aber noch auf github gibt.
Zum Schreiben mit Rmarkdown oder der Erweiterung Bookdwon braucht es nur die entsprechenden R-Pakete, für Quarto is nocht eine eigenständige Quarto-Installation nötig. Die ist hier zu finden.
Zuletzt wird ein Github-Repo2 benötigt.
Zur Einrichtung braucht es erst einen Github-Account, der Rest kann über die Github-Desktop-GUI erledigt werden.
Nach der Anmeldung in der GUI kann dafür einfach wie in Figure 1 zu sehen auf File -> New repository
geklickt oder Strg + N
gedrückt werden.
Im sich daraufhin öffnenden Dialog (Figure 2) kann das zu erstellende Repo eingerichtet werden. Neben Name, Beschreibung und lokalem Speicherort kann hier auch eine Lizenz und ein gitignore-Vorbild angegeben werden. Das gitignore-File gibt an, welche Dateien grundsätzlich nicht ins Repo aufgenommen werden sollen - für Projekte wie hier beschrieben bietet sich hier das R-Template an. Außerdem
Nach der lokalen Erstellung muss das Repo noch mit einem Github-remote verknüpft werden. Das kann einfach mit “Publish Repository” (Figure 3) geschehen, solange noch kein Repo mit dem entsprechenden Namen existiert.
Wenn sich nun in Github Web angemeldet wird, müsste das neue repository in der Liste auftauchen. Nach der o.g. Erstellung können im Repo unter den Einstellungen -> Collaborators noch Coautoren eingeladen werden.
Als Vorbereitung des Erstellens von Issues für Kommentare kann dem Repo noch die TODO to Issue Action hinzugefügt werden. Diese legt automatisch Issues an, wenn in einem Textfile ein TODO-Kommentar angelegt ist.
Zum Einbinden in das Repo muss im Repo ein Ordner namens .github
und darin einer namens workflows
angelegt werden.
In diesem workflows
-Ordner wird dann ein YAML file mit dem Namen TODO.yml
angelegt, das den folgenden Inhalt enthält:
name: "Run TODO to Issue"
on: ["push"]
jobs:
build:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v3"
- name: "TODO to Issue"
uses: "alstr/todo-to-issue-action@v4"
with:
AUTO_ASSIGN: true #Ersteller zuweisen wenn nicht anders angegeben
IDENTIFIERS: '[{"name": "COMMENT", "labels": ["comment"]}, {"name": "SUGGESTION", "labels": ["suggestion"]}]' # Liste mit Standard-Issue-Tags
Damit die Action läuft muss die Änderung noch ins Repo gepushed werden. Dazu einmal in Github Dektop committen (Figure 4) und dann pushen (Figure 5).
Schreiben
Um einen Artikel zu schreiben bietet sich an, entweder bookdown oder quarto zu nutzen. Beide unterstützen das Schreiben eines Übergeordneten Dokuments in einer Reihe von anderen Dokumenten, zum Beispiel aufgesplittet nach Kapiteln. Das Aufteilen ist nicht unbedingt nötig, kann aber das Zusammenarbeiten vereinfachen.
Das Arbeiten mit einem Quarto-Stack hat außerdem den Vorteil, dass Auswertung, Poster, Paper und Präsentation in einem Abwasch erledigt werden können und alles an einer Stelle gesammelt vorliegt.
Ein _quarto.yml
, das Zweck genutzt wird, könnte wie folgt aussehen:
project:
output-dir: _output
render:
- _quarto/paper.qmd
toc: false
number-sections: false
bibliography: references.bib
csl: _quarto/apa.csl
title: Testartikel
format:
html:
theme: cosmo
pdf:
documentclass: scrreprt
Der Text kann dann einfach in den einzelnen Textfiles runter geschrieben werden. Wenn mehrere Kapitel in einem Dokument eingebunden werden sollen, kann die includes-Syntax von Quarto genutzt werden. Der Ordner mit den Quarto-Files wurde in diesem Beispiel mit einem Unterstrich eingeleitet, damit beim Rendern nicht automatisch für jedes File ein Output generiert wird.
Formatierung in Quarto
Quarto bietet vielfältige Formatierungsoptionen, um das Aussehen von Texten und Grafiken anzupassen. Die offizielle Dokumentation enthält ausführliche Informationen und Beispiele zur Formatierung für verschiedene Output-Formate.
Tabellen und Grafiken können außerdem direkt in R oder Python Codechunks erstellt und eingebunden werden, Beispiele für gute Pakete zur Formatierung von Tabellen in R sind huxtable und kableExtra.
Für Grafiken führt in R natürlich kein Weg an ggplot vorbei, für Python ist seaborn eine gute Anlaufstelle.
Grafiken und Tabellen können dann über die Chunk-Optionen in Quarto beschriftet werden und über die in der Dokumentation beschriebenen Syntax Cross-referenziert werden. Mögliche Chunk-Optionen sind in der knitr-Referenz aufgelistet.
Zitate in Quarto
Zotero bietet in Kombination mit dem citr-Paket und Better BibTeX eine hervorragende Möglichkeit, Literaturverweise in Quarto-Dokumenten zu verwalten. Nach der Installation von Zotero und Better BibTeX kann entweder direkt über citr auf die Zotero Bibliothek (siehe die citr-Dokumentation oder auf ein aus Zotero exportiertes .bib-file zugegriffen werden. Im Quarto-Dokument kann dann auf Referenzen verwiesen werden, indem der folgende Passus in den _quarto.yml YAML-Header eingefügt wird:
bibliography: references.bib
csl: quarto/apa.csl
Über Addins -> CITR Insert citation kann die jeweilige Bibliothek durchsucht und die Referenz eingefügt werden. Wenn aus der Zotero-Bibliothek referenziert wird, wird das references.bib
-File automatisch ergänzt. Beim Rendern des Dokuments wird die Literatursammlung im unter cls im header angegebenen Format automatisch am Ende des Dokuments oder an der mit dem folgenden Inhalt angegebenen Stelle eingefügt:
::: {#refs}
:::
Format-Vorlagen auf Quarto-Dokumente anwenden
Quarto unterstützt die Verwendung von Format-Vorlagen, um das Design von Dokumenten anzupassen. Um z.B. eine LaTeX-Vorlage (wie zum Beispiel von einem Journal ausgegeben) auf ein Quarto-Dokument anzuwenden, müssen die folgenden Zeilen in den YAML-Header des Quarto-Dokuments eingefügt werden:
format:
pdf:
documentclass: my-template
includes:
in_header: my-template.tex
Weitere Informationen zum Anpassen von PDF-Dokumenten mit Quarto- und LaTeX-Vorlagen sind in der Quarto-Dokumentation zu finden.
Zusammenarbeit
Kommentieren
Dank der TODO to Issue Action werden Inline-Kommentare in den Quarto- oder R Markdown-Dateien direkt in GitHub Issues umgewandelt. Dies ist besonders nützlich, um Feedback oder Anmerkungen während des Schreibprozesses zu geben und vor allem Anmerkungen direkt diskutieren zu können. Um dieses Feature zu nutzen, müssen Kommentare zu einem Textabschnitt wie folgt direkt in das qmd-file geschrieben werden:
- Kommentare sollten mit TODO, COMMENT oder SUGGESTION beginnen und können in HTML- oder R-Kommentaren platziert werden. Hinter die Anmerkungsart muss in Klammern der github-tag des Kommentar-Autors genannt werden. Ein Kommentar könnte zum Beispiel so aussehen:
<!-- TODO(MBrede): Die Grafik könnte mehr Farbe vertragen.-->
- Mit “assignees:” kann eine Liste von Projektmitarbeitern angegeben werdne, die im Issue eingebunden und damit per Mail informiert werden soll:
<!-- TODO(MBrede): Die Grafik könnte mehr Farbe vertragen.
assignees: MBrede, vlerche-->
- Mit “labels:” können außerdem direkt Tags für das Issue angegeben werden:
<!-- TODO(MBrede): Die Grafik könnte mehr Farbe vertragen.
assignees: MBrede, vlerche
labels: ggplot2-->
Kleinere Änderungen können natürlich direkt im file umgesetzt werden. Bei größeren Umformulierungsvorschlag ist ein Beispiel im Kommentar aber eine einfachere Option, auch wenn einzelne vorgeschlagene Änderungen ausgewählt werden können.
Nach Durchgehen eines Files müssen die Änderungen ins repo zurückgespielt werden. Dazu einmal über die Github-GUI Committen mit einer möglichst beschreibenden Änderungszusammenfassung und über die Schaltfläche oben rechts Pushen.
Die TODO to Issue Action erstellt automatisch ein neues Issue für jeden Kommentar. Issues werden mit den entsprechenden Labels versehen, die in der .github/workflows/TODO.yml-Datei definiert und im Kommentar angegeben sind.
Wenn ein Issue erstellt wurde, kann das Issue diskutiert, bearbeitet und geschlossen werden, sobald es gelöst ist. Bei Entfernen des Kommentars wird das Issue auch direkt als geschlossen markiert.
Push/Pull-Workflow
Um Überblick über die Änderungshistorie zu behalten und die aktuellste Version von gerade in Bearbeitung befindlichen Abschnitten zu trennen, bietet GitHub den Pull-Request-Workflow:
- Jeder Autor erstellt einen neuen Branch für seine Änderungen.
- Nachdem die Änderungen vorgenommen wurden, erstellt der Autor einen Pull Request.
- optional können andere Autoren auf Wunsch die Änderungen überprüfen und Feedback geben und abschließend Pull Request genehmigen.
- Beim Erstellen des Pull-Requests kann ein Co-Autor getagged und damit benachrichtigt werden.
- Wenn alle Autoren (oder der/die Erst-Autor:in) mit den Änderungen einverstanden sind, wird der Pull Request in den Haupt-Branch gemerged.
Cherry-Picking und Blaming von Änderungen
Im gemeinsamen Schreibprozess kann es hilfreich sein, bestimmte Änderungen aus einem Branch in einen anderen zu übernehmen oder herauszufinden, wer eine bestimmte Änderung vorgenommen hat. Hier sind zwei nützliche Funktionen, die dabei helfen: Cherry-Picking und Blaming.
Cherry-Picking
Mit Cherry-Picking können gezielt einzelne Commits aus einem Branch in einen anderen übernommen werden. Dies ist besonders nützlich, wenn nur bestimmte Änderungen aus einem Branch genutzt werden sollen, ohne den gesamten Branch zu mergen. Die folgenden Schritte beschreiben, wie Cherry-Picking verwendet wird:
-
Zunächst muss sichergestellt werden, dass man sich auf dem gewünschten Ziel-Branch befindet, in den der Commit übernommen werden soll. Um den aktuellen Branch im Terminal zu überprüfen, kann der Befehl git branch verwendet werden. Der aktuelle Branch wird dabei mit einem Sternchen (*) gekennzeichnet.
-
Sollte der aktuelle Branch nicht der gewünschte Ziel-Branch sein, kann man mit dem Befehl git checkout
auf den richtigen Branch wechseln, wobei durch den tatsächlichen Namen des gewünschten Ziel-Branches ersetzt wird. -
Die Commit-ID des gewünschten Commits muss gefunden werden. Dies kann durch das Durchsuchen der Commit-Historie in GitHub Desktop oder auf der GitHub-Webseite erfolgen.
-
Ein Terminal wird geöffnet und zum lokalen Repository navigiert.
-
Der Befehl git cherry-pick
wird ausgeführt, wobei durch die tatsächliche Commit-ID ersetzt wird. Dadurch wird der ausgewählte Commit in den aktuellen Branch übernommen.
Es ist auch möglich, nur bestimmte Änderungen aus einem Commit oder einem Branch zu übernehmen, ohne den gesamten Commit oder Branch zu übernehmen. Eine Möglichkeit besteht darin, git cherry-pick mit der Option -n (oder –no-commit) sowie git reset und git checkout zu verwenden:
-
Zunächst muss wieder sichergestellt werden, dass man sich auf dem gewünschten Ziel-Branch befindet, in den die Änderungen übernommen werden sollen. Um den aktuellen Branch im Terminal zu überprüfen, kann der Befehl git branch verwendet werden. Der aktuelle Branch wird dabei mit einem Sternchen (*) gekennzeichnet.
-
Sollte der aktuelle Branch nicht der gewünschte Ziel-Branch sein, kann man mit dem Befehl git checkout
auf den richtigen Branch wechseln, wobei durch den tatsächlichen Namen des gewünschten Ziel-Branches ersetzt wird. -
Die Commit-ID des gewünschten Commits muss gefunden werden. Dies kann durch das Durchsuchen der Commit-Historie in GitHub Desktop oder auf der GitHub-Webseite erfolgen.
-
Der Befehl git cherry-pick -n
wird ausgeführt, wobei durch die tatsächliche Commit-ID ersetzt wird. Dadurch werden die Änderungen aus dem ausgewählten Commit in den aktuellen Branch übernommen, aber noch nicht committet. -
Mit git checkout HEAD
können nun gezielt Änderungen aus bestimmten Dateien rückgängig gemacht werden, wobei durch den tatsächlichen Dateinamen ersetzt wird. Dies entfernt die unerwünschten Änderungen aus dem Arbeitsverzeichnis und lässt nur die gewünschten Änderungen übrig. -
Schließlich kann git add
verwendet werden, um die gewünschten Änderungen zum Commit vorzumerken, und git commit -m “ ” zum Erstellen eines neuen Commits mit diesen Änderungen, wobei durch den tatsächlichen Dateinamen und durch eine aussagekräftige Commit-Nachricht ersetzt wird.
Blaming
Die Git-Blame-Funktion ermöglicht es, herauszufinden, wer eine bestimmte Änderung in einer Datei vorgenommen hat. Dies kann nützlich sein, um die Verantwortung für bestimmte Änderungen oder Entscheidungen im Text nachzuvollziehen. Die folgenden Schritte beschreiben, wie Blaming verwendet wird:
-
Auf der GitHub-Webseite navigiert man zum gewünschten Repository und öffnet die betreffende Datei.
-
Klickt man auf die Schaltfläche “Blame” (zu finden oben rechts in der Dateiansicht), wird eine Ansicht angezeigt, in der jede Zeile der Datei mit dem entsprechenden Autor und Commit gekennzeichnet ist.
-
In dieser Ansicht kann man nachverfolgen, wer welche Änderung vorgenommen hat und wann dies geschah. Bei Bedarf kann man auf den Commit-Link klicken, um weitere Informationen zum Commit und dessen Kontext zu erhalten.
Dieser Prozess stellt sicher, dass alle Änderungen sorgfältig überprüft werden und hilft, Konflikte und Fehler zu vermeiden.