Git
Chapters ▾ 2nd Edition

2.2 Git Grundlagen - Änderungen nachverfolgen und im Repository speichern

Änderungen nachverfolgen und im Repository speichern

An dieser Stelle sollten Sie ein originalgetreues Git-Repository auf Ihrem lokalen Computer und eine Checkout- oder Arbeitskopie aller seiner Dateien vor sich haben. Normalerweise werden Sie damit beginnen wollen, Änderungen vorzunehmen und Schnappschüsse dieser Änderungen in Ihr Repository zu übertragen, wenn das Projekt so weit fortgeschritten ist, dass Sie es sichern möchten.

Denken Sie daran, dass sich jede Datei in Ihrem 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). Alle Dateien, die sich im letzten Schnappschuss (Commit) befanden, werden in der Versionsverwaltung nachverfolgt. Sie können entweder unverändert, modifiziert oder für den nächsten Commit vorgemerkt (staged) sein. Kurz gesagt sind getrackte, versionierte Dateien, Daten, die Git kennt.

Alle anderen Dateien in Ihrem 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 Sie ein Repository zum ersten Mal klonen, sind alle Dateien versioniert und unverändert. Nach dem Klonen wurden sie ja ausgecheckt und bis dahin haben Sie ja auch noch nichts an ihnen verändert.

Sobald Sie anfangen, versionierte Dateien zu bearbeiten, erkennt Git diese als modifiziert, weil sie sich im Vergleich zum letzten Commit verändert haben. Die geänderten Dateien können Sie dann für den nächsten Commit vormerken und schließlich alle Änderungen, die sich in der Staging-Area befinden, einchecken/committen. Danach wiederholt sich der Zyklus.

Der Status Ihrer Dateien im Überblick
Figure 8. Der Status Ihrer Dateien im Überblick

Zustand von Dateien prüfen

Das wichtigste Hilfsmittel, um den Zustand zu überprüfen, in dem sich Ihre Dateien gerade befinden, ist der Befehl git status. Wenn Sie 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 directory 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 Ihnen der Befehl mit, auf welchem Branch Sie gerade arbeiten und informiert Sie 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; Sie müssen sich jetzt nicht darum kümmern. Wir werden im Kapitel Git Branching auf Branches detailliert eingehen.

Nehmen wir einmal an, Sie fügen eine neue Datei mit dem Namen README zu Ihrem Projekt hinzu. Wenn die Datei zuvor nicht existiert hat und Sie jetzt git status ausführen, 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. Git nimmt eine solche Datei nicht automatisch in die Versionsverwaltung auf, sondern Sie müssen Git dazu ausdrücklich auffordern. Ansonsten würden generierte Binärdateien oder andere Dateien, die Sie nicht in Ihrem Repository haben möchten, 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, können Sie den Befehl git add verwenden. Für Ihre neue README Datei, können Sie folgendes ausführen:

$ git add README

Wenn Sie den git status Befehl erneut ausführen, werden Sie sehen, dass sich Ihre 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 reset HEAD <file>..." to unstage)

    new file:   README

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

Geänderte Dateien zur Staging-Area hinzufügen

Lassen Sie uns jetzt eine bereits versionierte Datei ändern. Wenn Sie zum Beispiel eine bereits unter Versionsverwaltung stehende Datei mit dem Dateinamen CONTRIBUTING.md ändern und danach den Befehl git status erneut ausführen, erhalten Sie 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 „Changed but 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ühren Sie 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 wird oft missverstanden, viele assoziieren damit, dass damit Dateien zum Projekt hinzufügt werden. Wie Sie aber gerade gelernt haben, wird der Befehl auch noch für viele andere Dinge eingesetzt. Wenn Sie den Befehl git add einsetzen, sollten Sie das eher so sehen, dass Sie damit einen bestimmten Inhalt für den nächsten Commit vormerken. Lassen Sie 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, Sie wollen jetzt aber noch eine weitere Änderung an der Datei CONTRIBUTING.md vornehmen, bevor Sie den Commit tatsächlich starten. Sie öffnen die Datei erneut, ändern sie entsprechend ab und eigentlich wären Sie ja jetzt bereit den Commit durchzuführen. Allerdings lassen Sie 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 Sie den Befehl git add ausführen. Wenn Sie den Commit jetzt anlegen, wird die Version der Datei CONTRIBUTING.md denjenigen Inhalt haben, den sie hatte, als Sie git add zuletzt ausgeführt haben – und nicht denjenigen, den sie in dem Moment hat, wenn Sie den Befehl git commit ausführen. Wenn Sie stattdessen die gegenwärtige Version im Commit haben möchten, müssen Sie 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 Sie Ihre Änderungen kompakter sehen können. Wenn Sie git status -s oder git status --short ausführen, erhalten Sie 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, haben ?? neben sich, neue Dateien, die dem 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 Verzeichnisbaums. 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 Ihrem Build-System erzeugt werden. In solchen Fällen können Sie 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 der 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. Sie können 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 Ihr neues Repository einzurichten, noch bevor Sie loslegen. So können Sie nicht versehentlich Dateien committen, die Sie wirklich nicht in Ihrem Git-Repository haben möchten.

Die Richtlinien für Vergleichsmuster, die Sie in der Datei .gitignore eingeben können, lauten wie folgt:

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

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

  • Sie können Vergleichsmuster mit einem Schrägstrich (/) beginnen, um die Rekursivität zu verhindern.

  • Sie können Vergleichsmuster mit einem Schrägstrich (/) beenden, um ein Verzeichnis anzugeben.

  • Sie können ein Vergleichsmuster verbieten, indem Sie es mit einem Ausrufezeichen (!) beginnen.

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). Sie können auch zwei Sterne verwenden, um verschachtelte Verzeichnisse abzugleichen; a/**/z würde zu a/z, a/b/z, a/b/c/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
Tip

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 Sie einen Ansatzpunkt für Ihr Projekt suchen.

Note

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

Überprüfen der Staged und Unstaged Änderungen

Wenn der Befehl git status für Sie zu vage ist – Sie wollen genau wissen, was Sie geändert haben, nicht nur welche Dateien geändert wurden – können Sie den Befehl git diff verwenden. Wir werden git diff später ausführlicher behandeln, aber Sie werden es wahrscheinlich am häufigsten verwenden, um diese beiden Fragen zu beantworten: Was hat sich geändert, ist aber noch nicht zum Commit vorgemerkt (engl. staged)? Und was haben Sie zum Commit vorgemerkt und können es demnächst committen? Der Befehl git status beantwortet diese Fragen ganz allgemein, indem er die Dateinamen auflistet, git diff zeigt Ihnen aber genau die hinzugefügten und entfernten Zeilen – sozusagen den Patch.

Nehmen wir an, Sie bearbeiten und merken die Datei README zum Commit vor (eng. stage) und bearbeiten dann die Datei CONTRIBUTING.md, ohne sie zu „stagen“. Wenn Sie den Befehl git status ausführen, sehen Sie erneut so etwas wie das hier:

$ 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 Sie noch nicht zum Commit vorgemerkt haben, geben Sie 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 Ihrem Arbeitsverzeichnis befindet, mit dem, was sich in Ihrer Staging-Area befindet. Die Bildschirmanzeige gibt Ihnen an, welche Änderungen Sie vorgenommen haben, die noch nicht „gestaged“ sind.

Wenn Sie wissen wollen, was Sie zum Commit vorgemerkt haben, das in Ihren nächsten Commit einfließt, können Sie git diff --staged verwenden. Dieser Befehl vergleicht Ihre zum Commit vorgemerkten Änderungen mit Ihrem 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 Ihrem letzten Commit anzeigt – nur die Änderungen, die noch „unstaged“ sind. Wenn Sie alle Ihre Änderungen bereits „gestaged“ haben, wird git diff Ihnen keine Antwort geben.

Ein weiteres Beispiel: wenn Sie die Datei CONTRIBUTING.md zum Commit vormerken und dann wieder bearbeiten, können Sie mit git diff die Änderungen in der „staged“ Datei und die „unstaged“ Änderungen sehen. Wenn Sie folgendes gemacht haben:

$ 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

Jetzt können Sie 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 Ihnen, was Sie bisher zum Commit vorgemerkt haben (--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
Note
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, wenn Sie lieber ein graphisches oder externes Diff-Viewing-Programm bevorzugen. Wenn Sie git difftool anstelle von git diff verwenden, können Sie alle diese Unterschiede in einer Software wie emerge, vimdiff und viele andere (einschließlich kommerzieller Produkte) anzeigen lassen. Führen Sie den Befehl git difftool --tool-help aus, um zu sehen, was auf Ihrem System verfügbar ist.

Die Änderungen committen

Nachdem Ihre Staging-Area nun so eingerichtet ist, wie Sie es wünschen, können Sie Ihre Änderungen committen. Denken Sie daran, dass alles, was noch nicht zum Commit vorgemerkt ist – alle Dateien, die Sie erstellt oder geändert haben und für die Sie seit Ihrer Bearbeitung nicht mehr git add ausgeführt haben – nicht in diesen Commit einfließen werden. Sie bleiben aber als geänderte Dateien auf Ihrer Festplatte erhalten. In diesem Beispiel nehmen wir an, dass Sie beim letzten Mal, als Sie git status ausgeführt haben, gesehen haben, dass alles zum Commit vorgemerkt wurde und bereit sind, Ihre Änderungen zu committen. Am einfachsten ist es, wenn Sie git commit eingeben:

$ git commit

Dadurch wird der Editor Ihrer Wahl gestartet. (Das wird durch die Umgebungsvariable EDITOR Ihrer Shell festgelegt – normalerweise vim oder emacs, wie Sie es mit dem Befehl git config --global core.editor beliebig konfigurieren können und wie Sie es in Kapitel 1, Erste Schritte, gesehen haben).

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

Sie können erkennen, dass die Standard-Commit-Meldung die neueste Ausgabe des auskommentierten Befehls git status und eine leere Zeile darüber enthält. Sie können diese Kommentare entfernen und Ihre Commit-Nachricht eingeben oder Sie können sie dort stehen lassen, damit Sie sich merken können, was Sie committen. (Für eine noch bessere Gedächtnisstütze über das, was Sie geändert haben, können Sie die Option -v an git commit übergeben. Dadurch wird auch die Differenz Ihrer Änderung in den Editor geschrieben, so dass Sie genau sehen können, welche Änderungen Sie committen.) Wenn Sie den Editor verlassen, erstellt Git Ihren Commit mit dieser Commit-Nachricht (mit den Kommentaren und ausgeblendetem diff).

Alternativ können Sie Ihre Commit-Nachricht auch inline mit dem Befehl commit -m eingeben. Das -m Flag ermöglicht die direkte Eingabe eines Kommentar-Textes:

$ 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 haben Sie Ihren ersten Commit erstellt! Sie können sehen, dass der Commit eine Nachricht über sich selbst ausgegeben hat: in welchen Branch Sie committed haben (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.

Denken Sie daran, dass der Commit den Snapshot aufzeichnet, den Sie in Ihrer Staging-Area eingerichtet haben. Alles, was von Ihnen nicht zum Commit vorgemerkt wurde, liegt immer noch als modifiziert da. Sie können einen weiteren Commit durchführen, um es zu Ihrer Historie hinzuzufügen. Jedes Mal, wenn Sie einen Commit ausführen, zeichnen Sie einen Schnappschuss Ihres Projekts auf, auf den Sie zurückgreifen oder mit einem späteren Zeitpunkt vergleichen können.

Die Staging Area überspringen

Obwohl es außerordentlich nützlich sein kann, Commits so zu erstellen, wie Sie es wünschen, ist die Staging-Area manchmal etwas komplexer, als Sie es für Ihren Workflow benötigen. Wenn Sie 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 vorgemerkt (engl. staged), so dass Sie den Teil git add überspringen können:

$ 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 'added new benchmarks'
[master 83e38c7] added new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

Beachten Sie, dass Sie in diesem Fall git add nicht auf der Datei CONTRIBUTING.md ausführen müssen, bevor Sie committen. Das liegt daran, dass das -a Flag alle geänderten Dateien einschließt. Das ist bequem, aber seien Sie vorsichtig. Manchmal führt dieses Flag dazu, dass Sie ungewollte Änderungen vornehmen.

Dateien löschen

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

Wenn Sie die Datei einfach aus Ihrem Arbeitsverzeichnis entfernen, erscheint sie unter dem „Changes not staged for commit“ Bereich (das ist die unstaged-Area) Ihrer 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 Sie dann git rm ausführen, 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 Sie das nächste Mal einen Commit ausführen, ist die Datei weg und ist nicht mehr versioniert (engl. tracked). Wenn Sie die Datei geändert oder bereits zur Staging-Area hinzugefügt haben, müssen Sie 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 Sie möglicherweise nutzen möchten, ist, die Datei in Ihrem Verzeichnisbaum zu behalten, sie aber aus Ihrer Staging-Area zu entfernen. Mit anderen Worten, Sie können die Datei auf Ihrer Festplatte behalten, aber nicht mehr von Git protokollieren/versionieren lassen. Das ist besonders dann nützlich, wenn Sie vergessen haben, etwas zu Ihrer .gitignore Datei hinzuzufügen und diese versehentlich „gestaged“ haben, wie eine große Logdatei oder eine Reihe von .a kompilierten Dateien. Das erreichen Sie mit der Option --cacheed:

$ git rm --cached README

Sie können Dateien, Verzeichnisse und Platzhalter-Zeichen an den Befehl git rm übergeben. Das bedeutet, dass Sie folgende Möglichkeit haben:

$ git rm log/\*.log

Beachten Sie den Backslash (\) vor dem *. Der ist notwendig, weil Git zusätzlich zur Dateinamen-Erweiterung Ihrer Shell eine eigene Dateinamen-Erweiterung vornimmt. Mit dem Befehl oben werden alle Dateien entfernt, die die Erweiterung .log im Verzeichnis log/ haben. oder, Sie können etwas Ähnliches ausführen:

$ git rm \*~

Das Kommando entfernt alle Dateien, deren Name mit einer ~ endet.

Dateien verschieben

Im Gegensatz zu vielen anderen VCS-Systemen verfolgt (engl. track) Git das Verschieben von Dateien nicht ausdrücklich. Wenn Sie eine Datei in Git umbenennen, werden keine Metadaten in Git gespeichert, die dem System mitteilen, dass Sie die Datei umbenannt haben. 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 Sie eine Datei in Git umbenennen möchten, dann können Sie beispielsweise Folgendes ausführen:

$ git mv file_from file_to

Das funktioniert gut. Tatsache ist, wenn Sie so einen Befehl ausführen und sich den Status ansehen, werden Sie 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 Sie eine Datei auf diese Weise oder mit dem Befehl mv umbenennen. Der alleinige, reale Unterschied ist, dass git mv ein einziger Befehl ist statt deren drei – es ist eine Komfortfunktion. Wichtiger ist, dass Sie jedes beliebige Tool verwenden können, um eine Datei umzubenennen und das add/rm später aufrufen können, bevor Sie committen.