Git
Chapters ▾ 2nd Edition

2.2 Git Grundlagen - Änderungen nachverfolgen und im Repository speichern

Änderungen nachverfolgen und im Repository speichern

An dieser Stelle solltest du ein angemessenes Git-Repository auf deinem lokalen Computer und eine Checkout- oder Arbeitskopie aller deiner Dateien vor dir haben. Normalerweise wirst du damit beginnen wollen, Änderungen vorzunehmen und Schnappschüsse dieser Änderungen in dein Repository zu committen, wenn das Projekt so weit fortgeschritten ist, dass du es sichern möchten.

Denke daran, dass sich jede Datei in deinem Arbeitsverzeichnis in einem von zwei Zuständen befinden kann: tracked oder untracked – Änderungen an der Datei werden verfolgt (engl. tracked) oder eben nicht (engl. untracked). Tracked Dateien sind Dateien, die im letzten Snapshot enthalten sind. Genauso wie alle neuen Dateien in der Staging-Area. Sie können entweder unverändert, modifiziert oder für den nächsten Commit vorgemerkt (staged) sein. Kurz gesagt, nachverfolgte Dateien sind Dateien, die Git kennt.

Alle anderen Dateien in deinem Arbeitsverzeichnis dagegen, sind nicht versioniert: Das sind all diejenigen Dateien, die nicht schon im letzten Schnappschuss enthalten waren und die sich nicht in der Staging-Area befinden. Wenn du ein Repository zum ersten Mal klonst, sind alle Dateien versioniert und unverändert. Nach dem Klonen wurden sie ja ausgecheckt und bis dahin hast du auch noch nichts an ihnen verändert.

Sobald du anfängst versionierte Dateien zu bearbeiten, erkennt Git diese als modifiziert, weil sie sich im Vergleich zum letzten Commit verändert haben. Die geänderten Dateien kannst du dann für den nächsten Commit vormerken und schließlich alle Änderungen, die sich in der Staging-Area befinden, einchecken (engl. committen). Danach wiederholt sich dieser Vorgang.

Der Status deiner Dateien im Überblick
Abbildung 8. Der Status deiner Dateien im Überblick

Zustand von Dateien prüfen

Das wichtigste Hilfsmittel, um den Zustand zu überprüfen, in dem sich deine Dateien gerade befinden, ist der Befehl git status. Wenn du diesen Befehl unmittelbar nach dem Klonen eines Repositorys ausführen, sollte er in etwa folgende Ausgabe liefern:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

Dieser Zustand wird auch als sauberes Arbeitsverzeichnis (engl. clean working directory) bezeichnet. Mit anderen Worten, es gibt keine Dateien, die unter Versionsverwaltung stehen und seit dem letzten Commit geändert wurden – andernfalls würden sie hier aufgelistet werden. Außerdem teilt dir der Befehl mit, auf welchem Branch du gerade arbeitest und informiert dich darüber, dass dieser sich im Vergleich zum Branch auf dem Server nicht verändert hat. Momentan ist dieser Zweig immer master, was der Vorgabe entspricht; Du musst dich jetzt nicht darum kümmern. Wir werden im Kapitel Git Branching detaillierter auf Branches eingehen.

Anmerkung

GitHub änderte Mitte 2020 den Standard-Branch-Namen von master in main, und andere Git-Hosts folgten diesem Beispiel. Daher wirst du möglicherweise feststellen, dass der Standard-Branch-Name in einigen neu erstellten Repositorys main und nicht master ist. Außerdem kann der Standard-Branch-Name geändert werden (wie du in Der standardmäßige Branch-Name gesehen hast), sodass du möglicherweise einen anderen Namen für den Standard-Branch vorfindest.

Git selbst verwendet jedoch immer noch master als Standard, also werden wir es auch im gesamten Buch verwenden.

Nehmen wir einmal an, du fügst eine neue Datei mit dem Namen README zu deinem Projekt hinzu. Wenn die Datei zuvor nicht existiert hat und du jetzt git status ausführst, zeigt Git die bisher nicht versionierte Datei wie folgt an:

$ echo 'My Project' > README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README

nothing added to commit but untracked files present (use "git add" to track)

Alle Dateien, die im Abschnitt „Untracked files“ aufgelistet werden, sind Dateien, die bisher noch nicht versioniert sind. Dort wird jetzt auch die Datei README angezeigt. Mit anderen Worten, die Datei README wird in diesem Bereich gelistet, weil sie im letzten Schnappschuss nicht enthalten war und noch nicht gestaged wurde. Git nimmt eine solche Datei nicht automatisch in die Versionsverwaltung auf. Du musst Git dazu ausdrücklich auffordern. Ansonsten würden generierte Binärdateien oder andere Dateien, die du nicht in deinem Repository haben möchtest, automatisch hinzugefügt werden. Das möchte man in den meisten Fällen vermeiden. Jetzt wollen wir aber Änderungen an der Datei README verfolgen und fügen sie deshalb zur Versionsverwaltung hinzu.

Neue Dateien zur Versionsverwaltung hinzufügen

Um eine neue Datei zu versionieren, kannst du den Befehl git add verwenden. Für deine neue README Datei, kannst du folgendes ausführen:

$ git add README

Wenn du erneut den Befehl git status ausführst, wirst du sehen, dass sich deine README Datei jetzt unter Versionsverwaltung befindet und für den nächsten Commit vorgemerkt ist:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)

    new file:   README

Du kannst erkennen, dass die Datei für den nächsten Commit vorgemerkt ist, weil sie unter der Rubrik „Changes to be committed“ aufgelistet ist. Wenn du jetzt einen Commit anlegst, wird der Schnappschuss den Zustand der Datei festhalten, den sie zum Zeitpunkt des Befehls git add hat. Du erinnerst dich vielleicht daran, wie du vorhin git init und anschließend git add <files> ausgeführt hast. Mit diesen Befehlen hast du die Dateien in deinem Verzeichnis zur Versionsverwaltung hinzugefügt. Der Befehl git add akzeptiert einen Pfadnamen einer Datei oder eines Verzeichnisses. Wenn du ein Verzeichnis angibst, fügt git add alle Dateien in diesem Verzeichnis und allen Unterverzeichnissen rekursiv hinzu.

Geänderte Dateien zur Staging-Area hinzufügen

Las uns jetzt eine bereits versionierte Datei ändern. Wenn du zum Beispiel eine bereits unter Versionsverwaltung stehende Datei mit dem Dateinamen CONTRIBUTING.md änderst und danach den Befehl git status erneut ausführst, erhältst du in etwa folgende Ausgabe:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Die Datei CONTRIBUTING.md erscheint im Abschnitt „Changes not staged for commit“. Das bedeutet, dass eine versionierte Datei im Arbeitsverzeichnis verändert worden ist, aber noch nicht für den Commit vorgemerkt wurde. Um sie vorzumerken, führst du den Befehl git add aus. Der Befehl git add wird zu vielen verschiedenen Zwecken eingesetzt. Man verwendet ihn, um neue Dateien zur Versionsverwaltung hinzuzufügen, Dateien für einen Commit vorzumerken und verschiedene andere Dinge – beispielsweise einen Konflikt aus einem Merge als aufgelöst zu kennzeichnen. Leider wird der Befehl git add oft missverstanden. Viele assoziieren damit, dass damit Dateien zum Projekt hinzugefügt werden. Wie du aber gerade gelernt hast, wird der Befehl auch noch für viele andere Dinge eingesetzt. Wenn du den Befehl git add einsetzt, solltest du das eher so sehen, dass du damit einen bestimmten Inhalt für den nächsten Commit vormerkst. Las uns nun mit git add die Datei CONTRIBUTING.md zur Staging-Area hinzufügen und danach das Ergebnis mit git status kontrollieren:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Beide Dateien sind nun für den nächsten Commit vorgemerkt. Nehmen wir an, du willst jetzt aber noch eine weitere Änderung an der Datei CONTRIBUTING.md vornehmen, bevor du den Commit tatsächlich startest. Du öffnest die Datei erneut, änderst sie entsprechend ab und eigentlich wärst du jetzt bereit den Commit durchzuführen. Las uns vorher noch einmal den Befehl git status ausführen:

$ vim CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Was zum Kuckuck …​? Jetzt wird die Datei CONTRIBUTING.md sowohl in der Staging-Area als auch als geändert aufgelistet. Wie ist das möglich? Die Erklärung dafür ist, dass Git eine Datei in exakt dem Zustand für den Commit vormerkt, in dem sie sich befindet, wenn du den Befehl git add ausführst. Wenn du den Commit jetzt anlegst, wird die Version der Datei CONTRIBUTING.md denjenigen Inhalt haben, den sie hatte, als du git add zuletzt ausgeführt hast und nicht denjenigen, den sie in dem Moment hat, wenn du den Befehl git commit ausführst. Wenn du stattdessen die gegenwärtige Version im Commit haben möchten, müsst du erneut git add ausführen, um die Datei der Staging-Area hinzuzufügen:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Kompakter Status

Die Ausgabe von git status ist sehr umfassend und auch ziemlich wortreich. Git hat auch ein Kurzformat, mit dem du deine Änderungen kompakter sehen kannst. Wenn du git status -s oder git status --short ausführst, erhältst du eine kürzere Darstellung des Befehls:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

Neue Dateien, die nicht versioniert werden, werden mit ?? markiert. Neue Dateien, die der Staging-Area hinzugefügt wurden, haben ein A, geänderte Dateien haben ein M usw. Es gibt zwei Spalten für die Ausgabe – die linke Spalte zeigt den Status der Staging-Area und die rechte Spalte den Status des Arbeitsverzeichnis. So ist beispielsweise in der Bildschirmausgabe oben die Datei README im Arbeitsverzeichnis geändert, aber noch nicht staged, während die Datei lib/simplegit.rb geändert und staged ist. Das Rakefile wurde modifiziert, staged und dann wieder modifiziert, so dass es Änderungen an ihm gibt, die sowohl staged als auch unstaged sind.

Ignorieren von Dateien

Häufig gibt es eine Reihe von Dateien, die Git nicht automatisch hinzufügen oder schon gar nicht als „nicht versioniert“ (eng. untracked) anzeigen soll. Dazu gehören in der Regel automatisch generierte Dateien, wie Log-Dateien oder Dateien, die von deinem Build-System erzeugt werden. In solchen Fällen kannst du die Datei .gitignore erstellen, die eine Liste mit Vergleichsmustern enthält. Hier ist eine .gitignore Beispieldatei:

$ cat .gitignore
*.[oa]
*~

Die erste Zeile weist Git an, alle Dateien zu ignorieren, die auf „.o“ oder „.a“ enden – Objekt- und Archivdateien, die das Ergebnis einer Codegenerierung sein könnten. Die zweite Zeile weist Git an, alle Dateien zu ignorieren, deren Name mit einer Tilde (~) enden, was von vielen Texteditoren wie Emacs zum Markieren temporärer Dateien verwendet wird. Du kannst auch ein Verzeichnis „log“, „tmp“ oder „pid“ hinzufügen, eine automatisch generierte Dokumentation usw. Es ist im Allgemeinen eine gute Idee, die .gitignore Datei für dein neues Repository einzurichten, noch bevor du loslegen. So kannst du nicht versehentlich Dateien committen, die du nicht in deinem Git-Repository haben möchtest.

Die Richtlinien für Vergleichsmuster, die du in der Datei .gitignore eingeben kannst, lautet wie folgt:

  • Leerzeilen oder Zeilen, die mit # beginnen, werden ignoriert.

  • Standard-Platzhalter-Zeichen funktionieren und werden rekursiv im gesamten Verzeichnisbaum angewendet.

  • Du kannst Vergleichsmuster mit einem Schrägstrich (/) beginnen, um die Rekursivität zu verhindern.

  • Du kannst Vergleichsmuster mit einem Schrägstrich (/) beenden, um ein Verzeichnis anzugeben.

  • Du kannst ein Vergleichsmuster negieren, indem es mit einem Ausrufezeichen (!) beginnt.

Platzhalter-Zeichen sind wie einfache, reguläre Ausdrücke, die von der Shell genutzt werden. Ein Sternchen (*) entspricht null oder mehr Zeichen; [abc] entspricht jedem Zeichen innerhalb der eckigen Klammern (in diesem Fall a, b oder c); ein Fragezeichen (?) entspricht einem einzelnen Zeichen und eckige Klammern, die durch einen Bindestrich ([0-9]) getrennte Zeichen einschließen, passen zu jedem Zeichen dazwischen (in diesem Fall von 0 bis 9). Du kannst auch zwei Sterne verwenden, um verschachtelte Verzeichnisse abzugleichen; a/**/z würde zu a/z, a/b/z, a/b/c/z usw. passen.

Hier ist eine weitere .gitignore Beispieldatei:

# ignore all .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in any directory named build
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf
Hinweis

GitHub unterhält eine ziemlich umfassende Liste guter .gitignore Beispiel-Dateien für Dutzende von Projekten und Sprachen auf https://github.com/github/gitignore, falls du einen Ansatzpunkt für dein Projekt suchst.

Anmerkung

Im einfachsten Fall kann ein Repository eine einzelne .gitignore Datei in seinem Root-Verzeichnis haben, die rekursiv für das gesamte Repository gilt. Es ist aber auch möglich, weitere .gitignore Dateien in Unterverzeichnissen anzulegen. Die Regeln dieser verschachtelten .gitignore Dateien gelten nur für die in dem Verzeichnis (und unterhalb) liegenden Dateien. Das Linux-Kernel-Source-Repository hat beispielsweise 206 .gitignore Dateien.

Es würde den Rahmen dieses Buches sprengen, detaillierter auf den Einsatz mehrerer .gitignore Dateien einzugehen; siehe die Manpage man gitignore für weitere Informationen.

Überprüfen der Staged- und Unstaged-Änderungen

Wenn der Befehl git status zu wage für dich ist und du genau wissen willst, was du geändert hast, kannst du den Befehl git diff verwenden. Wir werden git diff später ausführlicher behandeln, aber du wirst es wahrscheinlich oft verwenden, um dir diese beiden Fragen zu beantworten: Was hat sich geändert, ist aber noch nicht zum Commit vorgemerkt (engl. staged)? Was hast du zum Commit vorgemerkt und wird demnächst committet? Der Befehl git status beantwortet diese Fragen ganz allgemein, indem er die Dateinamen auflistet; git diff zeigt dir aber genau die hinzugefügten und entfernten Zeilen – sozusagen den aktuellen Patch.

Nehmen wir an, du bearbeitest und stagst die Datei README nochmal und bearbeitest dann die Datei CONTRIBUTING.md, ohne sie zu stagen. Wenn du den Befehl git status ausführst, siehst du erneut so etwas:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Um die Änderungen zu sehen, die du noch nicht zum Commit vorgemerkt hast, gibst du den Befehl git diff ohne weitere Argumente, ein:

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's

Dieses Kommando vergleicht, was sich in deinem Arbeitsverzeichnis befindet, mit dem, was sich in deiner Staging-Area befindet. Das Ergebnis gibt dir an, welche Änderungen du vorgenommen hast, die noch nicht gestaged sind.

Wenn du wissen willst, was du zum Commit vorgemerkt hast, das in deinem nächsten Commit einfließt, kannst du git diff --staged verwenden. Dieser Befehl vergleicht deine zum Commit vorgemerkten Änderungen mit deinem letzten Commit:

$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project

Es ist wichtig zu wissen, dass git diff von sich aus nicht alle Änderungen seit deinem letzten Commit anzeigt – nur die Änderungen, die noch „unstaged“ sind. Wenn du alle deine Änderungen bereits „gestaged“ hast, wird git diff dir keine Antwort geben.

Ein weiteres Beispiel: Wenn du die Datei CONTRIBUTING.md stagst und dann bearbeitest, kannst du git diff verwenden, um die Änderungen in der Datei anzuzeigen, die staged und nicht staged sind. Wenn es bei dir so aussieht:

$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   CONTRIBUTING.md

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

kannst du jetzt mit git diff sehen, was noch nicht zum Commit vorgemerkt ist

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
 ## Starter Projects

 See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line

und git diff --cached zeigt an, was du bisher zum Commit vorgemerkt hast (--staged und --cached sind Synonyme, sie bewirken das Gleiche):

$ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's
Anmerkung
Git Diff mit einem externen Tool

Wir werden den Befehl git diff im weiteren Verlauf des Buches auf vielfältige Weise verwenden. Es gibt eine weitere Methode, diese Diffs zu betrachten, solltest du lieber ein graphisches oder externes Diff-Viewing-Programm bevorzugen. Wenn du git difftool anstelle von git diff verwendest, könntest du alle diese Unterschiede in einer Software wie emerge, vimdiff und viele andere (einschließlich kommerzieller Produkte) anzeigen lassen. Führe einfach den Befehl git difftool --tool-help aus, um zu sehen, was auf deinem System verfügbar ist.

Die Änderungen committen

Nachdem deine Staging-Area nun so eingerichtet ist, wie du es wünschst, kannst du deine Änderungen committen. Denke daran, dass alles, was noch nicht zum Commit vorgemerkt ist – alle Dateien, die du erstellt oder geändert hast und für die du seit deiner Bearbeitung nicht mehr git add ausgeführt hast – nicht in diesen Commit einfließen werden. Sie bleiben aber als geänderte Dateien auf deiner Festplatte erhalten. In diesem Beispiel nehmen wir an, dass du beim letzten Mal, als du git status ausgeführt hast, gesehen hast, dass alles zum Commit vorgemerkt wurde und du bereit bist, alle deine Änderungen zu committen. Am einfachsten committen man, wenn git commit eingegeben wird:

$ git commit

Dadurch wird der Editor deiner Wahl gestartet.

Anmerkung

Das wird durch die Umgebungsvariable EDITOR deiner Shell festgelegt – normalerweise Vim oder Emacs. Du kannst den Editor aber auch mit dem Befehl git config --global core.editor beliebig konfigurieren, wie du es in Kapitel 1, Erste Schritte gesehen hast.

Der Editor zeigt den folgenden Text an (dieses Beispiel ist eine Vim-Ansicht):

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
#	new file:   README
#	modified:   CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C

Du kannst erkennen, dass die Standard-Commit-Meldung die neueste Ausgabe des auskommentierten Befehls git status und eine leere Zeile darüber enthält. Du kannst diese Kommentare entfernen und deine eigene Commit-Nachricht eingeben oder du kannst sie dort stehen lassen, damit du dir merken kannst, was was du committed hast.

Anmerkung

Für eine noch bessere Gedächtnisstütze über das, was du geändert hast, kannst du die Option -v an git commit übergeben. Dadurch wird auch die Änderung in den Editor geschrieben, so dass du genau sehen kannst, welche Änderungen du committest.

Wenn du den Editor verlässt, erstellt Git deinen Commit mit dieser Commit-Nachricht (mit den Kommentaren und ausgeblendetem Diff).

Alternativ kannst du deine Commit-Nachricht auch inline mit dem Befehl commit -m eingeben. Das Flag -m ermöglicht die direkte Eingabe eines Kommentartextes:

$ git commit -m "Story 182: fix benchmarks for speed"
[master 463dc4f] Story 182: fix benchmarks for speed
 2 files changed, 2 insertions(+)
 create mode 100644 README

Jetzt hast du deinen ersten Commit erstellt! Du kannst sehen, dass der Commit eine Nachricht über sich selbst ausgegeben hat: in welchen Branch du committet hast (master), welche SHA-1-Prüfsumme der Commit hat (463dc4f), wie viele Dateien geändert wurden und Statistiken über hinzugefügte und entfernte Zeilen im Commit.

Denke daran, dass der Commit den Snapshot aufzeichnet, den du in deiner Staging-Area eingerichtet hast. Alles, was von dir nicht zum Commit vorgemerkt wurde, ist weiterhin verfügbar. Du kannst einen weiteren Commit durchführen, um es zu deiner Historie hinzuzufügen. Jedes Mal, wenn du einen Commit ausführst, zeichnest du einen Schnappschuss deines Projekts auf, auf den du zurückgreifen oder mit dem du später vergleichen kannst.

Die Staging-Area überspringen

Obwohl es außerordentlich nützlich sein kann, Commits so zu erstellen, wie du es wünschst, ist die Staging-Area manchmal etwas komplexer, als du es für deinen Workflow benötigst. Wenn du die Staging-Area überspringen möchten, bietet Git eine einfache Kurzform. Durch das Hinzufügen der Option -a zum Befehl git commit wird jede Datei, die bereits vor dem Commit versioniert war, automatisch von Git zum Commit staged, so dass du den Teil git add überspringen kannst:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'Add new benchmarks'
[master 83e38c7] Add new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

Beachte, dass du in diesem Fall git add nicht für die Datei CONTRIBUTING.md ausführen musst, bevor du committest. Das liegt daran, dass das -a-Flag alle geänderten Dateien einschließt. Das ist bequem. Aber sei vorsichtig, manchmal führt dieses Flag dazu, dass du ungewollte Änderungen vornimmst.

Dateien löschen

Um eine Datei aus Git zu entfernen, musst du sie aus der Versionsverwaltung entfernen (genauer gesagt, aus deinem Staging-Bereich löschen) und dann committen. Der Befehl git rm erledigt das und entfernt die Datei auch aus deinem Arbeitsverzeichnis, so dass du sie beim nächsten Mal nicht mehr als „untracked“-Datei siehst.

Wenn du die Datei einfach aus deinem Arbeitsverzeichnis entfernst, erscheint sie unter dem „Changes not staged for commit“-Bereich (das ist die unstaged-Area) deiner git status Ausgabe:

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")

Wenn du dann git rm ausführst, wird die Entfernung der Datei zum Commit vorgemerkt:

$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    PROJECTS.md

Wenn du das nächste Mal einen Commit ausführst, ist die Datei weg und ist nicht mehr versioniert (engl. tracked). Wenn du die Datei geändert oder bereits zur Staging-Area hinzugefügt hast, musst du das Entfernen mit der Option -f erzwingen. Hierbei handelt es sich um eine Sicherheitsfunktion, die ein versehentliches Entfernen von Dateien verhindert, die noch nicht in einem Snapshot aufgezeichnet wurden und die nicht von Git wiederhergestellt werden können.

Eine weitere nützliche Sache, die du möglicherweise nutzen möchtest, ist, die Datei in deinem Verzeichnisbaum zu behalten, sie aber aus deiner Staging-Area zu entfernen. Mit anderen Worten, du kannst die Datei auf deiner Festplatte behalten, aber nicht mehr von Git protokollieren/versionieren lassen.

Das ist besonders dann nützlich, wenn du vergessen hast, etwas zu deiner Datei .gitignore hinzuzufügen und dies dann versehentlich gestaged hast (eine große Logdatei z.B. oder eine Reihe von .a-kompilierten Dateien). Das erreichst du mit der Option --cached:

$ git rm --cached README

Du kannst Dateien, Verzeichnisse und Platzhalter-Zeichen an den Befehl git rm übergeben. Das bedeutet, dass du folgende Möglichkeit hast:

$ git rm log/\*.log

Beachten den Backslash (\) vor dem *. Der ist notwendig, weil Git zusätzlich zur Dateinamen-Erweiterung deiner Shell eine eigene Dateinamen-Erweiterung vornimmt. Mit dem Befehl oben werden alle Dateien entfernt, die die Erweiterung .log im Verzeichnis log/ haben. Oder du kannst Folgendes ausführen:

$ git rm \*~

Dieses Kommando entfernt alle Dateien, deren Name mit ~ endet.

Dateien verschieben

Im Gegensatz zu vielen anderen VCS-Systemen verfolgt (engl. track) Git das Verschieben von Dateien nicht ausdrücklich. Wenn du eine Datei in Git umbenennst, werden keine Metadaten in Git gespeichert, die dem System mitteilen, dass du die Datei umbenannt hast. Allerdings ist Git ziemlich clever, das im Nachhinein herauszufinden – wir werden uns etwas später mit der Erkennung von Datei-Verschiebungen befassen.

Daher ist es etwas verwirrend, dass Git einen Befehl mv vorweisen kann. Wenn du eine Datei in Git umbenennen möchten, kannst du beispielsweise Folgendes ausführen:

$ git mv file_from file_to

Das funktioniert gut. Tatsache ist, wenn du so einen Befehl ausführst und dir den Status ansiehst, wirst du sehen, dass Git es für eine umbenannte Datei hält:

$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Unabhängig davon, ist dieser Befehl zu dem Folgenden gleichwertig:

$ mv README.md README
$ git rm README.md
$ git add README

Git erkennt, dass es sich um eine umbenannte Datei handelt, so dass es egal ist, ob du eine Datei auf diese Weise oder mit dem Befehl mv umbenennst. Der alleinige, reale Unterschied ist, dass git mv ein einziger Befehl ist statt deren drei – es ist eine Komfortfunktion. Wichtiger ist, dass du jedes beliebige Tool verwenden können, um eine Datei umzubenennen und das du add/rm später aufrufen kannst, bevor du committest.

scroll-to-top